继承和可见性 - PHP

20

我很难理解为什么我们会得到这段代码的输出:

<?php

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

所以Foo继承自Bar。$myfoo是Foo类的一个对象。Foo没有一个叫做test()的方法,因此它从父类Bar中继承了该方法。但为什么test()方法的结果是

Bar::testPrivate 
Foo::testPublic

当子类重写父类的方法时,为什么第一个不是Foo::testPrivate呢?

非常感谢您的帮助!

6个回答

12

可能是因为,正如名称所示,testPrivate 是一个私有方法,不会被类继承/覆盖。

在您从php.net手册页面获得的代码中,它明确说明了 我们可以重新声明公共和受保护的方法,但不能是 private

因此,实际发生的情况是:子类不会重新声明方法 testPrivate,而是在子对象的“范围”中创建自己的版本。由于 test() 在父类中定义,它将访问父类的 testPrivate 方法。

如果您在子类中重新声明 test 函数,则应访问子类的? testPrivate() 方法。


6

私有方法只对声明类可见。由于您从父类调用testPrivate,它只能访问自己声明的该方法。因此,您会看到您所看到的输出。但是如果访问修饰符为protected,则您将获得预期的输出,因为受保护的方法在整个继承链中都可见。


5

private成员不能被覆盖,只有公共和受保护的成员可以被覆盖。这意味着实际上testPrivate没有被覆盖,因此Bar无法看到它并且仍然调用自己的testPrivate


5
因为private意味着私有。其他类,甚至子类都不知道Bar::testPrivate()的存在,因此无法覆盖他们根本不知道的内容。
你只能在Foo内使用Foo::testPrivate()。这就是private的意义所在。
更多信息:当覆盖私有方法时的奇怪行为

3

这并不是PHP特有的问题。继承规则要求受保护和公共函数可以被覆盖。私有函数拥有自己的范围,并且对于一般化的类是不可见的。

请看下面Java中相同情况,结果也一样:

Bar::testPrivate

Foo::testPublic

除非您获得警告,否则不要这样做。
The method testPrivate() from the type Foo is never used locally    Foo.java    

由于 Java 是编译型语言。

public class Bar 
{
    public void test() {
        this.testPrivate();
        this.testPublic();
    }

    public void testPublic() {
        System.out.println("Bar::testPublic\n)");
    }

    private void testPrivate() {
        System.out.println( "Bar::testPrivate\n");
    }
}

public class Foo extends Bar {
    public void testPublic() {
        System.out.println("Foo::testPublic\n");
    }

    private void testPrivate() {
        System.out.println("Foo::testPrivate\n");
    }

    public static void main(String[] args) {
        Foo myFoo = new Foo();
        myFoo.test();
    }
}

3

来自手册

被声明为private的成员只能被定义该成员的类访问。

由于您的测试函数在基类Bar中运行,因此它将访问其自身类中的私有函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接