【问题标题】:Private method overriding and visibility私有方法覆盖和可见性
【发布时间】:2014-03-06 10:01:28
【问题描述】:

我很难理解以下代码的输出:

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

    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();

输出:

Foo::testPublic
Bar::testPrivate 

Foo 覆盖 testPublic()testPrivate(),并继承 test()。当我调用 test() 时,有一个包含 $this 伪变量的显式指令,所以在我创建 $myFoo 实例之后,最终调用test() 函数将是 $myFoo->testPublic()$myFoo->testPrivate()。第一个输出如我所料,因为我重写了 testPublic() 方法来回显 Foo::testPublic。但是第二个输出对我来说毫无意义。如果我覆盖 testPrivate() 方法,为什么是 Bar::testPrivate?根据定义,父类的私有方法也不会被继承!这没有道理。为什么调用的是父方法???

【问题讨论】:

  • 考虑将public function test() { $this->testPublic(); $this->testPrivate(); } 更改为public function test() { $this->testPublic(); static::testPrivate(); } - 然后阅读late static binding(特别是示例#3)
  • @MarkBaker 这些方法是在对象上下文中调用的,而不是静态的,因此后期静态绑定不适用。这是一个简单的可见性问题。
  • @rainfromheaven - 我确实在我的评论中专门引用了 Example #3,“static:: usage in a non-static context”.. .. 即在 object 环境中。后期静态绑定完全按照文档的那部分所述应用
  • @MarkBaker 我收回我之前的声明,你对后期静态绑定是对的 :)

标签: php oop visibility overriding


【解决方案1】:

您的代码的问题在于方法Bar::testPrivateprivate,因此它不能被子类覆盖。对于初学者,我建议您阅读 PHP 中的可见性 - http://www.php.net/manual/en/language.oop5.visibility.php。在那里您将了解到只有 publicprotected 类成员方法/属性可以被覆盖,private 不能。

作为一个很好的例子,尝试将Bar::testPrivate 方法的可见性更改为公共或受保护,而不更改示例代码中的任何其他内容。现在尝试运行您的测试。发生什么了?这个:

PHP 致命错误:对 Foo::testPrivate() 的访问级别必须受到保护(如在 Bar 类中)或更弱

最大的问题是:“为什么?”。好吧,您现在已经用私有Foo:testPrivate 覆盖了Bar::testPrivate。这个新的私有方法超出了Bar::test 的范围,因为私有类成员仅对其当前类可见,父/子类!

因此,如您所见,OOP 为类成员提供了一定程度的封装,如果您不花时间去理解它,可能会相当混乱。

【讨论】:

  • 信不信由你,我发布的代码来自您建议的链接,PHP 官方手册,关于可见性部分。这是示例 #2 的一部分。
  • 是的,虽然该示例没有解释它的作用,但它实际上说明了 private 可见性在方法覆盖方面的含义(它不能完成) .
  • 哦,我现在明白了。但我还有另一个问题。一个“受保护”的方法不应该被其他对象访问,但是这样就被访问了,对吧?这就像调用受保护方法的解决方法。不是破坏封装吗?
  • 不,它不会以任何方式破坏封装,因为它就是这样设计的。当父/子类是同一类的实例时,受保护的类成员可以访问(即,您正在使用受保护的成员扩展类)。 PS:如果满足您的需求,通常会选择答案
猜你喜欢
  • 2014-05-28
  • 2014-08-11
  • 1970-01-01
  • 2013-10-26
  • 2023-04-09
  • 2011-01-01
  • 2013-01-31
相关资源
最近更新 更多