【问题标题】:Unsuspected behaviour and context in php inheritancephp继承中的意外行为和上下文
【发布时间】:2016-03-06 11:59:00
【问题描述】:

我在 PHP 中遇到了一些非常奇怪的行为。我不知道这是否发生在所有其他 oop 语言中,所以这是一个额外的问题 - 是吗?好的,据我所知:

  1. 当您从基类继承某些内容时,您基本上是复制 - 将受保护的和公共的方法粘贴到子类中,而不是私有的。
  2. 您无法访问类私有成员。
  3. 调用具体实例的方法时,您应该在实例上下文中调用该方法,就好像它是他自己的类的方法一样,其中 $this 指向调用该方法的对象(类的实例) .

就我在纯 PHP 中进行的测试而言,这不是真的,我完全被迷住了。谁能解释一下这种奇怪的(对我来说)行为?

这里是测试代码:

<?php

class A {
    private function foo() {
        echo "Here are the private stuff that only A class knows about..." .     '</br>';
        echo "The class name of this function is" . __CLASS__ . '</br>';
    }
    public function test() {
        $this->foo();
    }
}

class B extends A {
}

class C extends A {
    private function foo() {
    }
}

$a = new A();
$a->test();
$b = new B();
$b->test();
$c = new C();
$c->test();

$reflectionA = new ReflectionClass($a);
$reflectionB = new ReflectionClass($b);
$reflectionC = new ReflectionClass($c);

var_dump($reflectionA->getMethods());
var_dump($reflectionB->getMethods());
var_dump($reflectionC->getMethods());
var_dump($reflectionB->hasMethod('foo'));

【问题讨论】:

  • 那么上面的代码有什么问题?
  • 例如,如果您将方法 test 复制粘贴到 B 类中,您将获得完全不同的行为。好的,我知道根据定义继承是紧密耦合,但是我没想到当您调用 B 类从 A 类继承的方法时,您调用该方法就好像它是 A 类的方法而不是 B 类的方法一样。在 C 中,我们有一个 C 的实例,我们有一个带有 $this 的函数测试,它指向 A 类 foo 而不是 C 类 foo。这对我来说相当令人不安。我需要一个解释。
  • 您偶然发现了“后期状态绑定”或“早期状态绑定”的问题。你可以阅读它以及它是如何在 php 中处理或控制的。
  • (顺便说一句:这就是为什么你使用“复制和粘贴”图片来解释 OOP 原则的原因之一。事情完全不同。)
  • 嗯,这应该是某种闭包吗?我的意思很明显,函数 foo 记得它是在哪里创建的?

标签: php oop inheritance


【解决方案1】:

好的,B 扩展了 A 并接收它的所有方法,而不是像你说的“复制”,而是接收对它们的访问,对那些不是私有的。它没有自己的私人foo(),但它有父母的测试,当你打电话时

$b->test();

php 了解,您在搜索什么,检查 B 中是否有任何 test() 方法 - 没有,因此它测试 A 中是否有任何方法 - 并找到并使用它。由于 A 有私有 foo(),它被 A 的方法 test() 调用 - 它也在工作。

对于 C,情况是一样的,只是它有自己的私有方法。但是A的方法foo()在A类中寻找方法foo(),所以也可以。

【讨论】:

  • 好吧,假设您在 A 类中有一个私有财产 - private $secretData = 'Some top secret data'; A 中的测试是 public function test(){echo $this->secretData;} 在同样的情况下,我们得到了 3 次最高机密的数据。我的意思是不应该私有财产是私有的吗?此外,如果我们在 A 类和 B 类中有两个同名的私有属性,并且 test() 引用该属性,它将始终调用 A,而不是我期望的 B 的私有属性。我认为这可能会导致一些奇怪的错误,不是吗?这是我们应该小心的事情,我知道会发生什么,我想知道为什么。
  • 是的,这有点奇怪,我同意。实际上,我更喜欢 Python 思考所有这些封装事物的方式:“我们都是成年人”:) 我对隐藏属性的期望不高,我对与我一起工作的人期望很高。
  • 那么这个功能只有 PHP 才有吗?
  • 我不懂多少语言,但在一些私人的东西可以访问。不是很直接,但他们可以。
猜你喜欢
  • 1970-01-01
  • 2013-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-12
  • 2021-07-10
  • 2016-03-03
  • 1970-01-01
相关资源
最近更新 更多