PHP如何在扩展类中使用父类对象变量?

Lar*_*rry 2 php

对不起,这似乎是一个初学者的问题.如何在其扩展类中访问父类对象变量?

class FOO {
  public $foo;
  function __construct() {
    $this->foo = 'string';
  }
}

class Parent {
  public $x;
  function __construct() {
    $this->x = new FOO();
    var_dump($x); // this works
  }
}

class Child extends Parent {
  public $y;
  function __construct() {
    var_dump($this->x); // appears to be NULL all the time
  }
}
Run Code Online (Sandbox Code Playgroud)

如何正确传递$ x的值或引用?

Eli*_*gem 8

你的Child班级有自己的x财产.孩子们继承了非私人的一切,所以所有publicprotected属性/方法都可用.您声明了该属性x,但在Parent调用构造函数之前,它尚未初始化.如果子类(在本例中Child)具有自己的构造函数,则会重写父构造函数,并且不会自动调用它

简而言之:您必须在子类中显式调用父代的构造函数:

class Child extends Parent
{
    protected $y = 'Some string';//you can initialize properties here, too
    //ALWAYS use access modifiers
    public function __construct()
    {
        parent::__construct();//explicit call to parent constructor
        var_dump($this->x);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意:如果父构造函数需要参数,则子项必须执行相同的操作(签名必须匹配).参数类型应该是兼容的(如果不是:存在违反合同的情况),并且您可能希望将参数传递给父构造函数,以便它也能完成它的工作.

具有构造函数创建类内部需要的新实例被认为是不好的做法,BTW.谷歌:SOLID,特别注意依赖注入Liskov原则,以及类型提示.
如果您仔细阅读材料,您就会明白为什么这是编写代码的更好方法:

class Dad
{
    /**
     * @var Foo
     */
    protected $x = null;

    public function __construct(Foo $foo)
    {
        $this->x = $foo;
    }
}
//child
class Son extends Dad
{
    /**
     * @var string
     */
    protected $y = 'Some string';

    public function __construct(Foo $foo)
    {
        parent::__construct($foo);
    }
    public function test()
    {
        $results = array();
        $results[] = '$this->x instanceof Foo ? '.($this->x instanceof Foo ? 'Of course!': 'No');
        $results[] '$this instanceof Son ? '.($this instanceof Son ? 'Yup' : 'No?');
        $results[] '$this instanceof Dad ? '.($this instanceof Dad ? 'Yes!' : 'No?');
        return $results;//methods don't echo, they return...
    }
}
$son = new Son(new Foo());
echo implode(PHP_EOL, $son->test());
Run Code Online (Sandbox Code Playgroud)

这段代码的输出将是

$this->x instanceof Foo ? Of Course!
$this instanceof Son ? Yup
$this instanceof Dad ? Yes!
Run Code Online (Sandbox Code Playgroud)

这似乎使许多(相对)新的人对OOP感到困惑,但是子类与其父类的类型相同.如果你考虑一下,这是有道理的.对于外部世界(即,在给定类的实例上工作的代码),只有公共方法是可见的.根据定义,一个孩子继承了所有公共的东西,所以对外界来说,它并不重要.
如果某段代码需要一个Dad实例来做某事,那么a Son也会起作用,因为所有的Dad提议,a Son也可以.子类唯一做的就是添加父类已经提供的功能.