PHP:为什么继承子类的方法访问父级的私有属性?

时间:2016-11-14 19:13:29

标签: php oop inheritance properties parent-child

PHP的属性和方法继承有多么奇怪。请参阅以下示例:

class A {
    private $foo = 'hello';

    function get() {
        return $this->foo;
    }
    function set($val) {
        $this->foo = $val;
    }
}

class B extends A {
    private $foo = 'world';

    function get() { // try inheriting this
        return $this->foo;
    }
    function set($val) {  // try inheriting this
        $this->foo = $val;
    }
}

现在让我们看看如果我们继承或定义方法,它会如何回应:

$b = new B();

/* If B defines getter: */
echo $b->get(); // 'world' 

/* If B inherits getter: */
echo $b->get(); // 'hello'

// Enter Setter!
$b->set('cosmos');

/* If B defines setter & inherits getter: */
echo $b->get(); // 'hello' 

/* If B inherits setter & defines getter: */
echo $b->get(); // 'world' 

/* If B defines or inherits both: */
echo $b->get(); // 'cosmos'

所以:当B类定义了getter时,它返回自己的私有$foo= "world")。但是,如果我从类B中删除getter,并且类B从类A继承了相同的方法,则它将返回父类A($foo)中的私有= "hello"属性。与setter一样。

我期待继承的方法始终访问实例化类的属性,而没有引用它们的祖先'私人财产。他们是私人的,有理由,不是吗?私人有副作用!如果我将支柱可见性更改为公共或受保护,则预期属性" world"和"宇宙"无论是定义还是继承方法,都会返回B类。

以下是上述每种情况的对象转储:

var_dump($b);

/* If B defines getter (Prop get from B): */

["foo":"B":private] · string(5) "world"
["foo":"A":private] · string(5) "hello"

/* If B inherits getter: (Prop get from A) */

["foo":"B":private] · string(5) "world"
["foo":"A":private] · string(5) "hello"

// Enter Setter!
$b->set('cosmos');

/* If B defines setter & inherits getter 
 * Prop set to B & get from A */

["foo":"B":private] · string(6) "cosmos"
["foo":"A":private] · string(5) "hello"

/* If B defines getter & inherits setter
 * :: Prop set to A & get from B */

["foo":"B":private] · string(5) "world"
["foo":"A":private] · string(6) "cosmos"

/* If B defines both:
 * :: Prop set to B & get from B */

["foo":"B":private] · string(6) "cosmos"
["foo":"A":private] · string(5) "hello"

/* If B inherits both:
 * :: Prop set to A & get from A: */

["foo":"B":private] · string(5) "world"
["foo":"A":private] · string(6) "cosmos"

有人可以向我解释发生了什么的逻辑吗?继承的属性访问方法是否绑定到原始方法定义父类的私有属性?我不希望将相同的方法复制粘贴到每个具有匹配名称的私有属性的子类中。

如果上面的插图令人作呕,请打扰一下。不得不为了我自己的理智而拼出这个 - 意外的行为,除非我错过了一些明显的东西。 (N.B.在子类构造函数中使用构造函数或调用parent::__construct()对此行为没有影响。)

添加:现在更进一步。如果我声明getter受保护,并在B类中创建一个公共方法来获取变量。像这样:

class B {...
    public function getpro_direct() {
        return $this->foo;
    }
    public function getpro_getter() {
        return $this->get();
    }
...}

echo $b->getpro_direct(); // "world" (from B)
echo $b->getpro_getter(); // "hello" (from A)

如果我从A继承这两个方法,我会在两个方面得到"hello"。但如果我在B中定义get(),我会得到"你好"和#34;世界"分别。你好世界你好,宇宙呼唤。我需要一些果汁。

编辑让你们想知道我为什么会这样做。简短的背景故事:我正在研究一个在(数组)属性中更深入地增长的类层次结构,每个子类在同一个向量中是一个不太抽象的版本。 (请向您展示示例。)我正在以最聪明的方式将儿童的扩展属性与每个连续的父母进行合并。

到目前为止,私有声明是阻止子类覆盖父属性的唯一方法,因为我可以通过使用父getter同时获得两者的属性。然而,这会破坏方法继承,如此处所示。我想尽可能自动完成这项工作;最好使用单个clone_parent()方法继承并在每个孩子的构造函数中运行。我宁愿避免为每个父子扩展跳拼出单独的克隆符。 (我已经在这里搜索和阅读了一堆,但还是找到了一个令人满意的解决方案。)

Edit2:其他待处理的方法,根据我的实际关注点(如上所述)导致此实验。为了简单起见,我只是抛弃了子属性中的重叠声明,并调用extend_props方法,该方法添加了从arent继承的道具。 (唉,我希望每个扩展课程的附加内容都显示在上面,而不是潜入下面的方法!)

1 个答案:

答案 0 :(得分:0)

Private propertiesnot accessible outside his own class

如果您要扩展课程,他们也无法在外面访问。你"看到父母的私有财产的原因"是你在父母中定义了getter。这个getter可以访问私有属性,因为他在同一个类中。这并不奇怪。

我建议您详细了解privateprotectedpublic