【问题标题】:PHP how to use parent-class object variables in extended classes? [duplicate]PHP如何在扩展类中使用父类对象变量? [复制]
【发布时间】:2014-08-24 15:49:27
【问题描述】:

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

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 的值或引用?

【问题讨论】:

  • 它为null,因为您需要在Child构造中调用父Parent构造parent::__construct()

标签: php


【解决方案1】:

您的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);
    }
}

请注意:如果父构造函数需要一个参数,那么子构造函数也必须这样做(签名必须匹配)。参数类型应该是兼容的(如果不兼容:违反合同),您可能希望将参数传递给父构造函数,以便它也能完成它的工作。

让构造函数创建类内部需要的新实例被认为是不好的做法,顺便说一句。 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 也可以做到。子类唯一要做的就是添加到父类已经提供的功能。

【讨论】:

    【解决方案2】:

    你需要在 Child 的构造函数中调用 Parent 的构造函数,它不会自动调用:

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

    【讨论】:

      【解决方案3】:

      正确的代码是:

      <?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();
      

      此外,您不能使用Parent 作为类名,但我相信您是手工编写此代码并没有对其进行测试(我已将此代码中的Parent 类名更改为Parents

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-25
        • 2011-11-15
        • 2020-04-09
        • 1970-01-01
        • 2012-01-06
        相关资源
        最近更新 更多