我很难理解以下代码的输出:
class Bar
{
public function test() {
$this->testPublic();
$this->testPrivate();
}
public function testPublic() {
echo"Bar::testPublic
";
}
private function testPrivate() {
echo"Bar::testPrivate
";
}
}
class Foo extends Bar
{
public function testPublic() {
echo"Foo::testPublic
";
}
private function testPrivate() {
echo"Foo::testPrivate
";
}
}
$myFoo = new foo();
$myFoo->test();
输出:
Foo::testPublic
Bar::testPrivate
类foo重写testpublic()和testprivate(),并继承test()。当我调用test()时,有一个显式的指令envolving$这个伪变量,所以在我创建了$myfoo实例之后,test()函数的最终调用将是$myfoo->testpublic()和$myfoo->testprivate()。第一个输出如我所料,因为我将testpublic()方法覆盖到echo foo::testpublic。但是第二个输出对我来说毫无意义。如果我超越了testpprivate()方法,为什么是bar::testpprivate?另外,根据定义,父类的私有方法也不会被继承!这毫无意义。为什么要调用父方法????
考虑将public function test() { $this->testPublic(); $this->testPrivate(); }改为public function test() { $this->testPublic(); static::testPrivate(); },然后阅读后期静态绑定(特别是示例3)。
@markbaker这些方法是在对象上下文中调用的,而不是静态的,因此后期的静态绑定不适用。这是一个简单的可见性问题。
@我在我的评论中特别提到了示例3,"static::usage in a non-static context"……也就是说,在一个对象上下文中。后期静态绑定完全适用于文档的该部分
@Markbaker我收回了我之前的声明,你说的静态绑定是正确的:)
代码的问题在于方法Bar::testPrivate是private,因此它不能被子类重写。对于初学者,我建议您阅读php中的可见性-http://www.php.net/manual/en/language.oop5.visibility.php。在这里,您将了解到只有public和protected类成员方法/属性可以被重写,而private类成员方法/属性不能被重写。
作为一个好例子,尝试将Bar::testPrivate方法的可见性更改为public或protected,而不更改示例代码中的任何其他内容。现在尝试运行测试。发生什么事了?这是:
PHP Fatal error: Access level to Foo::testPrivate() must be protected (as in class Bar) or weaker
大问题是:"为什么?"你现在用一个私人的Foo:testPrivate覆盖了Bar::testPrivate。这个新的私有方法超出了Bar::test的范围,因为私有类成员只对当前类可见,而不是父类/子类!
因此,正如您所看到的,OOP为类成员提供了一定数量的封装,如果您不花时间去理解它,这会非常令人困惑。
信不信由你,我发布的代码来自你建议的链接,PHP官方手册,关于可见性部分。这是示例2的一部分。
是的,虽然这个例子缺乏对它所做工作的解释,但它实际上说明了private可见性在方法重写(它不能做到)方面的含义。
哦,我现在明白了。但我还有一个问题。一个"受保护"的方法不应该从其他对象访问,但是这样它就被访问了,对吗?调用一个受保护的方法就像一个解决方法。它不是破坏了封装吗?
不,它不会以任何方式破坏封装,因为它是这样设计的。当受保护的类成员是同一类的实例(即,您正在用受保护的成员扩展类)时,它们可以被父类/子类访问。附言:按照惯例,如果一个答案能满足你的需要,就选择它。