php手动可见性示例混淆

Posted

技术标签:

【中文标题】php手动可见性示例混淆【英文标题】:php manual visibility example confused 【发布时间】:2012-09-29 10:41:27 【问题描述】:

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

http://www.php.net/manual/en/language.oop5.visibility.php

这个例子输出

Bar::testPrivate 
Foo::testPublic

请您解释一下这是怎么发生的?

为什么两个testPublic() 都没有被调用?

我在 Bar 类构造中放置了一个 var_dump($this)。它打印object(Foo)[1]。我知道的是私有属性可以在同一个类中调用。

那么“Bar::testPrivate”是怎么调用的呢?

【问题讨论】:

【参考方案1】:

那么“Bar::testPrivate”是怎么调用的呢?

当您调用$myFoo->test() 时,它会在Bar 的上下文中运行代码,因为Foo 类没有覆盖它。

Bar::test() 内部,当$this->testPrivate() 被调用时,解释器将首先查看Foo,但该方法是私有的(并且不能从Bar 调用来自后代类的私有方法),所以它继续上一级直到找到合适的方法;在本例中为Bar::testPrivate()

相比之下,当$this->testPublic() 被调用时,解释器会立即在Foo 中找到合适的方法并运行它。

编辑

为什么两个 testPublic() 都没有被调用?

当您运行$this->testPublic() 时,只有一个方法被调用,这是最远的一个(就与基类的距离而言)。

如果Foo::testPublic() 还需要执行父级的实现,则应在该方法中写入parent::testPublic()

【讨论】:

+1 为什么不能test()(即Bartest())调用FootestPrivate()?因为它是私密的,您不希望父母触碰孩子的隐私,对吗? 我想,关于 testPublic() 的部分困惑是 PHP 会替换覆盖而不是细化覆盖。这意味着 PHP 不会在子级中调用父级的方法,除非您明确要求它这样做(例如:parent::testPublic();)。 @Jack 谢谢兄弟。你解释得很好。现在我可以理解重点了。因为 $this 指的是 foo,所以我认为应该调用 Foo 类的私有函数。这是我困惑的地方。【参考方案2】:

您的函数位于Barclass 中,并且您正在使用神奇的$this 指针来调用成员函数。

尝试将函数 test() 移动到 Foo 类,看看会发生什么。输出应为:

Foo::testPrivate
Foo::testPublic

在您的示例中,调用了 Bar 的私有函数,因为它仅适用于该类。 Foo 类中没有 test 函数,因此 Bar 类中的测试函数无权调用它们。

然后,由于函数重载,调用了类 Foo 的公共函数而不是 Bar 的公共函数。

两个类都有同名的函数,所以子类的函数很重要。

【讨论】:

【参考方案3】:

你打电话

$myFoo->test();

见函数test

public function test() 
    $this->testPrivate();
    $this->testPublic();

当在 Bar 类(包括继承的类)的实例上调用它时,它会调用 testPrivatetestPublic

这些方法在类Foo 中被覆盖,这意味着使用Foo 的方法。您可以随时调用基类的方法:

// in Foo
public function testPublic() 
    parent::testPublic();
    echo "Foo::testPublic\n";
    

Bar::testPrivate 被调用是因为它是private 并且未被Foo::testPrivate 覆盖。

查看更多here 或here。

【讨论】:

【参考方案4】:

Private 并不意味着你不能调用它。这意味着您只能从 当前类 中调用它。 Public 表示您可以从任何类调用它。

要拨打Bar::testPrivate,试试这个:

$Bar->testPublic();

parent::testPublic();

但是,你不能调用$Bar->testPrivate(),因为方法是private

【讨论】:

这不能回答问题。 抱歉,问题误解了。固定。【参考方案5】:

我猜用户 'omega at 2093 dot es' (http://www.php.net/manual/en/language.oop5.visibility.php#109324) 的评论描述了同样的事情。 有人说:“在父类中定义的方法不能访问从它们继承的类中定义的私有方法。但是它们可以访问受保护的。”

在您的情况下,Bar::test() 方法中的 $this 对象属于 Foo 类型(您的 var_dump 证明了这一点)。因为Foo::testPrivate()方法是私有的,所以不能从父类Bar访问,唯一可以访问的方法仍然是Bar::testPrivate()(尝试注释定义,你会得到致命错误)。这就是为什么第一个输出是Bar::testPrivate

$this->testPublic(); 行调用Foo::testPublic() 方法,因为$thisFoo 类型并且方法被定义为public。

简而言之,私有方法只能从定义它们的类中访问。它们既不能从子类也不能从父类访问。

为了使方法可以从子类或父类访问,使其受到保护。例如,如果您要在两个类中保护 testPrivate() 方法,它将打印 Foo::testPrivate Foo::testPublic

【讨论】:

【参考方案6】:

Foo 类扩展了 Bar 类。然后调用函数测试,它在 Bar 中定义。在这个函数中有两个调用。一个用于公共函数,一个用于 Bar 类中的私有函数。

【讨论】:

以上是关于php手动可见性示例混淆的主要内容,如果未能解决你的问题,请参考以下文章

使用 JavaScript 更改 DIV 可见性

php 类常量可见性

php获取可见性

将 XAML 中的可见性绑定到可见性属性

PHP中默认类的可见性是啥?

PHP 接口:指定任何可见性