请通过下面给出的代码来自php手册
<?php
class A {
private function foo() {
echo "success!\n";
}
public function test() {
$this->foo();
static::foo();
}
}
class B extends A {
/* foo() will be copied to B, hence its scope will still be A and
* the call be successful */
}
class C extends A {
private function foo() {
/* original method is replaced; the scope of the new one is C */
}
}
$b = new B();
$b->test();
$c = new C();
$c->test(); //fails
?>
任何人都可以解释这里到底发生了什么吗?
为什么将foo()复制到B?
答案 0 :(得分:4)
我现在记得为什么后期静态绑定很有用。不幸的是,php.net的例子很难解释。见这(修改)的例子:
<?php
class A {
private function foo() {
echo __CLASS__;
}
public function test() {
$this->foo();
static::foo();
}
}
class B extends A {
public function foo()
{
echo __CLASS__;
}
}
$b = new B();
$b->test();
?>
如果你运行上面的代码,你会发现它有效,你会得到AB
。为什么呢?
test()
是foo()
的公共getter,所以如果从test()
类型的对象或对象调用A
并不重要类型B
,继承自A
,因为test()
将始终可以访问定义它的类的私有成员。$this->foo();
将始终调用A::foo()
,因为绑定是在A
的范围内本地完成的,这有时是非常不受欢迎的。请参阅此评论:http://www.php.net/manual/en/language.oop5.late-static-bindings.php#83502 static::foo();
指示口译员确定$b
的类型,并查看在哪个班级中尝试查找foo()
。在这种情况下,B::foo()
被视为A::foo()
的覆盖方法,因此,基本上,如果B::foo()
存在,则会调用它,否则,解释器将查找A::foo()
}。B::foo()
标记为私有并运行我提供的示例,以查看会发生什么。我认为这个测试和我上面的咆哮将为你澄清问题;)另外,我接受对上述观点的任何评论,因为我很长一段时间没有使用PHP。
答案 1 :(得分:2)
foo
本身并未复制到B(它是继承的但是不可见;请参阅下面的Gordon评论)。 B继承A->foo
,调用A->test
。要进行演示,请查看echo __CLASS__
和test
内foo
发生的情况(并删除导致错误的static::foo()
调用):
class A {
private function foo() {
echo __CLASS__."->foo\n";
echo "success!\n";
}
public function test() {
echo __CLASS__."->test\n";
$this->foo();
}
}
输出:
A->test
A->foo
success!
A->test
A->foo
success!
这是继承的基本原则之一,因为它与information hiding / encapsulation有关。这允许你做这样的事情:
class ListOfThings {
// internal structure (top secret!)
private $_list = array();
// add item to list
public function add($item) {
$this->_list[] = $item;
}
// return number of items in list
public function count() {
return count($this->_list);
}
}
class ListOfStates extends ListOfThings {
// do we have all 50 states?
public function allStatesListed() {
return $this->count() === 50;
}
// try to access internal structure of ListOfThings
public function accessInternalStructure() {
sort($this->_list);
}
}
$states = new ListOfStates;
$states->add('ME');
$states->add('NH');
$states->add('VT');
$states->add('RI');
$states->add('CT');
var_dump($states->count());
var_dump($states->allStatesListed());
$states->accessInternalStructure();
输出:
int(5)
bool(false)
Warning: sort() expects parameter 1 to be array, null given...
如您所见,ListOfStates
能够使用ListOfThings
的所有公共功能,即使这些功能都依赖于私有变量$_list
。也就是说,ListOfStates
无法直接操纵$_list
;它只能通过$_list
中定义的公共函数间接地对ListOfThings
起作用。
查看PHP文档中的Visibility页面,了解有关此类内容的更多详细信息。