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()
(即Bar
的test()
)调用Foo
的testPrivate()
?因为它是私密的,您不希望父母触碰孩子的隐私,对吗?
我想,关于 testPublic()
的部分困惑是 PHP 会替换覆盖而不是细化覆盖。这意味着 PHP 不会在子级中调用父级的方法,除非您明确要求它这样做(例如:parent::testPublic();
)。
@Jack 谢谢兄弟。你解释得很好。现在我可以理解重点了。因为 $this 指的是 foo,所以我认为应该调用 Foo 类的私有函数。这是我困惑的地方。【参考方案2】:
您的函数位于Bar
class 中,并且您正在使用神奇的$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
类(包括继承的类)的实例上调用它时,它会调用 testPrivate
和 testPublic
。
这些方法在类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()
方法,因为$this
是Foo
类型并且方法被定义为public。
简而言之,私有方法只能从定义它们的类中访问。它们既不能从子类也不能从父类访问。
为了使方法可以从子类或父类访问,使其受到保护。例如,如果您要在两个类中保护 testPrivate()
方法,它将打印 Foo::testPrivate Foo::testPublic
。
【讨论】:
【参考方案6】:Foo 类扩展了 Bar 类。然后调用函数测试,它在 Bar 中定义。在这个函数中有两个调用。一个用于公共函数,一个用于 Bar 类中的私有函数。
【讨论】:
以上是关于php手动可见性示例混淆的主要内容,如果未能解决你的问题,请参考以下文章