【问题标题】:Parent's protected properties inaccessible to child object子对象无法访问父对象的受保护属性
【发布时间】:2019-10-06 07:38:10
【问题描述】:

我有一个父类,我将称之为“ParentClass”和一个子类(从它扩展而来),我将称之为“ChildClass”。

  • ParentClass 具有我希望 ChildClass 访问的受保护属性 $prop1 和 $prop2。但我从他们那里得到了 NULL。

  • ParentClass 有一个 __construct() 方法,它设置通过依赖注入接收的属性。

  • ParentClass 从其方法之一实例化 ChildClass。

  • ChildClass 覆盖父构造函数,但在其自己的 __construct() 方法中不包含任何代码。

我已经用 var_dump($this->prop1) 测试了父类的属性。它返回我期望的值。

但是,如果我从子类中 var_dump($this->prop1),我会得到 NULL。

class ParentClass {

    protected $prop1;

    protected $prop2;

    public function __construct($prop1, $prop2) {

        $this->prop1 = $prop1;

        $this->prop2 = $prop2;

    }

    public function fakeMethod() {

        $child = new ChildClass;
        $child->anotherFakeMethod();

        // logic

    }

}
class ChildClass extends ParentClass {

    public function __construct() {

        // this overrides the parent constructor

    }

    public function anotherFakeMethod() {

        $prop1 = $this->prop1;
        $prop2 = $this->prop2;

        var_dump($this->prop1);
        // returns NULL

    }

}

如果从父类扩展,为什么子类不能访问父类的属性?

【问题讨论】:

  • 您没有从子构造函数方法将数据注入父级。它为空的原因。如果它不是“可访问”,你会得到一个错误。

标签: php oop inheritance visibility


【解决方案1】:

它们是可访问的,但它们将是null,因为它们没有从子构造函数传递给父构造函数:

(new ChildClass(1,2))->anotherFakeMethod();

Sandbox

输出

NULL

在这种情况下,您的类会产生null 的预期结果。好吧,它会根据它的编码方式产生我期望的结果。

要修复它,您必须通过子类的构造函数将该数据传递回父类,或者删除子类的构造函数。像这样:

class ChildClass extends ParentClass {

    public function __construct($prop1, $prop2) {
         parent::__construct($prop1, $prop2);
    }
....
}

以上改动后:

(new ChildClass(1,2))->anotherFakeMethod();

输出

int(1)

Sandbox

这是我对这一行的期望,因为它基本上是构造函数中使用的第一个参数:

var_dump($this->prop1);

如果你知道它们在子类中是什么,你也可以这样做:

public function __construct() {
     parent::__construct(1, 2); //say I know what these are for this child
}

您当然可以在新的构造函数中手动设置它们,但在这种情况下,这将是 WET(将所有内容写入两次)或不必要的重复。

干杯!

【讨论】:

  • 谢谢。这行得通。但是,我仍然不明白为什么这是必要的。父类的构造函数在实例化时被调用,填充属性。那么为什么我们必须在子类中做任何事情呢?
  • @Doug 不,不是因为你用一个什么都不做的构造函数覆盖了它。要么不要覆盖它,要么像 ArtisticPhoenix 建议的那样做并使用parent::__construct($prop1, $prop2);
  • @Sammitch 说了什么。如果您只是在孩子中省略了它,那么它也可以工作。仅仅因为父类有一个同名的方法并不意味着 PHP 应该使用父类方法而不是子类的方法(如果它有相同的名称),事实上它恰恰相反。 PHP 应该并且确实使用当前类的方法,如果它在当前类中不存在,则回退到父类。如果它以另一种方式工作,您将永远无法覆盖子类中的方法,因为它总是会调用父类方法,这显然不是它应该如何工作的。
  • 只看代码可能会让人感到困惑,但是当你真正思考它是如何工作并拼写出来时,就像我在上面所做的那样,你会发现它是唯一可以工作的方式。
  • 再次感谢。我决定根本不创建子类的构造函数。当我从父级实例化子级时, $prop1 和 $prop2 在其构造函数中传递。这样我可以写更少的代码并完成我想要的。
猜你喜欢
  • 2013-01-05
  • 2013-10-02
  • 2013-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-10
  • 1970-01-01
相关资源
最近更新 更多