$ this对继承方法的行为

时间:2012-02-24 18:52:14

标签: php oop inheritance this

我一直以为我理解OOP是如何工作的(我多年来一直在使用它),但有时我意识到一些概念对我来说仍然不太清楚。

我刚刚遇到this question关于PHP中方法可见性的问题。 accepted answer解释了PHP中的子类不能覆盖私有方法。好的,这是有道理的。但是,这个例子让我想到了PHP中的内部继承机制,以及$this在继承方法上的行为方式。

考虑此代码(example from the PHP Manual,也包含在上述问题中):

class Bar 
{
    public function test() {
        $this->testPrivate();
        $this->testPublic();
    }

    public function testPublic() {
        echo "Bar::testPublic\n";
    }

    private function testPrivate() {
        echo "Bar::testPrivate\n";
    }
}

class Foo extends Bar 
{
    public function testPublic() {
        echo "Foo::testPublic\n";
    }

    private function testPrivate() {
        echo "Foo::testPrivate\n";
    }
}

$myFoo = new foo();
$myFoo->test();

/* 
Output:

Bar::testPrivate
Foo::testPublic
*/

现在考虑这个excerpt from the PHP Manual

  

从对象上下文中调用方法时,伪变量 $ this 可用。 $ this是对调用对象的引用(通常是方法所属的对象,但如果从辅助对象的上下文中静态调用该方法,则可能是另一个对象)。

说明中指出“$this是对调用对象的引用”,即$myFoo。所以我希望$myFoo->test()总是会调用Foo::testPrivate,而永远不会Bar::testPrivate(除非$myFooBar的实例)。我使用$thisget_class进行了测试,并始终返回Foo,即使是在Bar::testPrivateBar::test内也是如此。但是,当$this调用Bar时,Bar::test的行为类似于$this->testPrivate()的实例。

这真的令人困惑,我正在努力理解为什么它的工作原理!

我认为继承的方法(publicprotected)以某种方式从基类复制到子类。私有方法根​​本不会被复制。但是这个例子表明它不能像这样工作。看起来Foo的实例保留了Bar的内部实例,并在必要时委托方法调用。

我想在这里学习一些东西,而我只会在事情对我有意义的时候学习。这个没有。写完这些之后,我想我可以用两个问题来概括它:

  1. 有人可以简单解释一下继承如何在PHP内部内部工作吗?或者至少指向一篇关于它的文章或文档?

  2. 此处讨论的行为或$this是否也存在于其他OO语言中,还是特定于PHP?

2 个答案:

答案 0 :(得分:5)

PHP中的继承与大多数面向对象语言中的继承相同。

如果使用“虚拟”方法,则该方法不会直接绑定到调用方。相反,每个类都包含一个小的查找表,其中说“此方法名称绑定到该实现”。所以,当你说$this->testPublic()时,实际发生的是PHP:

  • 获取当前类的虚拟表
  • 在该表中查找testPublic的虚拟表条目
  • 调用查找点的方法

由于Foo会覆盖testPublic,因此其虚拟表包含指向testPublic的{​​{1}}条目。

现在,使用私有方法,行为是不同的。因为,正如您正确阅读的那样,私有方法无法被覆盖,调用私有方法永远不会导致虚拟表查找。也就是说,私有方法不能是虚方法,必须始终在使用它们的类中定义。

因此,效果是名称在声明时受到约束:所有Foo::testPublic方法在他们说Foo和所有Foo::testPrivate方法时会调用$this->testPrivate将致电Bar

总而言之,说“将继承的方法复制到子级”是不正确的。实际发生的是,子进程的方法名称查找表以其父类的条目填充,然后添加自己的函数并替换任何被覆盖的条目。当您致电Bar::testPrivate时,此查询表会参考获取当前对象的类。因此,如果$this->something$this的实例,并且Foo覆盖Foo,则会获得testPublic。如果Foo::testPublic$this的实例,您将获得Bar

答案 1 :(得分:2)

嗯,private方法和属性就是私有的。对于所有意图和目的,您可以将它们视为“内部”,意味着它们所定义的类的内部。这意味着它们永远不会被继承,并且永远不会被覆盖。

因此,当$thisprivate方法或属性结合使用时,它始终是与$this <的引用相同的类中的方法或属性 / em>的。发生这种情况是因为父类中调用的$this无法访问另一个类中的private方法或属性(因为它们是私有的),甚至来自子类

希望这有帮助。