请浏览下面给出的代码,它来自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 ?
我现在记得为什么后期静态绑定很有用。不幸的是,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()
的公共获取者,所以无论你是从A
类型的对象调用test()
,还是从继承自A
的B
类型的对象调用 都没有关系,因为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
foo
本身并没有被复制到B(它是继承的,但不可见;参见下面Gordon的评论)。B 继承 A->foo
,它调用 A->test
。若要演示,请查看从 test
和 foo
内部echo __CLASS__
时会发生什么情况(并删除导致错误的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!
这是继承的基础之一,因为它与信息隐藏/封装有关。这允许您执行以下操作:
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
;它只能通过ListOfThings
中定义的公共职能间接
$_list
。查看 PHP 文档中的可见性页面以获取有关此类内容的更多详细信息。