继承和可见性 - PHP

时间:2012-10-24 07:00:32

标签: php inheritance

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

<?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 个答案:

答案 0 :(得分:12)

正如名称已经暗示的那样,testPrivate可能是私有方法,并且不会被类继承继承/覆盖。

在php.net手册页上,您可能会从中明确说明We can redeclare the public and protected method, but not private

因此,具体如下:子类不会重新声明方法testPrivate,而是仅在子对象中在“范围”中创建自己的版本。由于test()在父类中定义,它将访问父项testPrivate

如果要重新声明子类中的test函数,它应该访问子项? testPrivate()方法。

答案 1 :(得分:5)

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

答案 2 :(得分:5)

除了声明类之外,其他任何内容都不会显示私有方法。由于您从父类调用testPrivate,因此它可以访问的唯一方法是它自己的方法声明。这样你就得到了你看到的输出。但是,如果访问修饰符为protected,那么您将获得所期望的输出,因为受保护的方法在整个继承链中都是可见的。

答案 3 :(得分:5)

因为private表示private。没有其他课程,甚至儿童课程都不了解Bar::testPrivate(),因此无法覆盖他们甚至不知道的事情。

您只能在Foo::testPrivate()内使用Foo。因为这就是private的全部内容。

更多信息:Strange behavior when overriding private methods

答案 4 :(得分:3)

来自manual

  

声明为私有的成员只能由该类访问   定义成员。

当您的测试函数在基类Bar中运行时,它将访问自己类中的私有函数。

答案 5 :(得分: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();
    }
}