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

PHP如何在扩展类中使用父类对象变量?,php,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 } } cl

很抱歉,这似乎是一个初学者的问题。 如何访问扩展类中的父类对象变量

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
  }
}

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

您的
子类有自己的
x
属性。子项继承非私有的所有内容,因此所有
public
protected
属性/方法都将可用。 您可以声明属性
x
,但在调用
父构造函数之前,它不会初始化。如果子类(在本例中为
子类
)有自己的构造函数,则父类构造函数将被重写,并且不会自动调用

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

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);
    }
}
注意:如果父构造函数需要一个参数,那么子构造函数也必须这样做(签名必须匹配)。参数类型应该是兼容的(如果不是:有违反约定的情况),并且您可能希望将参数传递给父构造函数,以便它也执行其工作

让构造函数创建类内部需要的新实例被认为是不好的做法,顺便说一句。Google:S.O.L.I.D.,特别注意依赖注入和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());
此代码的输出将是

$this->x instanceof Foo ? Of Course!
$this instanceof Son ? Yup
$this instanceof Dad ? Yes!
这似乎让许多(相对)不熟悉OOP的人感到困惑,但子类与其父类的类型相同。如果你仔细想想,这是有道理的。对于外部世界(即在给定类的实例上工作的代码),只有公共方法可见。根据定义,孩子继承了所有公开的东西,因此对于外界来说,这并不重要。

如果某段代码需要一个
Dad
实例来做某事,那么
Son
也会起作用,因为
Dad
提供的所有功能,
Son
也可以。子类所做的唯一事情就是添加到父类已经提供的功能中。

您需要在子类构造函数中调用父类构造函数,它不会自动调用:

class Child extends Parent {
    public $y;
    function __construct() {
       parent::__construct();
       var_dump($this->x); // appears to be NULL all the time
    }
}
正确的代码是:

<?php
error_reporting(E_ALL);
class FOO {
  public $foo;
  function __construct() {
    $this->foo = 'string';
  }
}

class Parents {
  public $x;
  function __construct() {
    $this->x = new FOO();
    var_dump($this->x); // fixed $x to $this->x
  }
}

class Child extends Parents {
  public $y;
  function __construct() {
    parent::__construct(); // you need to run Parents contructor
    var_dump($this->x); // appears to be NULL all the time
  }
}

$cl = new Child();

它是空的,因为您需要在
构造中调用父
构造
父::\uu construct()