class A {
private function foo() {
echo "a";
}
public function test() {
$this->foo();
}
}
class B extends A {
public function foo() {
echo 'b';
}
}
$b = new B();
$b->test();
结果是打印了a,而不是b。
我先阐明我的逻辑,答主们回答前务必要明白我的意思啊:
- A类的private function foo根据官方文档的解释是私有方法不会被继承到子类。那么,如果是这样的话,也就是说B类只继承了A类的test方法,B类现在有两个方法,自己的foo方法和从A继承过来的test方法。
- 但是,网上还有一种说法是,无论什么访问属性,都会被子类继承,只是private的方法或者属性子类并访问不到。那么,如果是这样的话,B类继承了A类的两个方法,并重写了从A类继承过来的foo方法。
- 无论以上两种可能哪一种是正确的,也就是说,无论B是有自己的foo方法还是B重写了foo方法,B的foo的函数体都是
echo 'b';
那么问题来了,为什么执行b的test方法,明明是执行的$this->foo();
,为什么不是B的foo,而是A的foo呢?
已经采纳回答,采纳 @代码宇宙 的原因请看答案评论区域,同时,推荐这片文章:https://www.2cto.com/kf/20100...
3.16 更新
昨天陷入了思维的怪圈,今天再来总结一下:
- 当子类继承父类之后,this的指向是动态绑定的,也就是说,当父类的方法被重写之后,调用的就是子类的方法,没有重写,就调用父类的方法。就是这么简单。
- 在这个问题中,父类的foo方法是私有的,并没有继承给子类,也就没有重写之说,所以,根据前面的定论,没有重写就调用父类中的方法。所以就打印了'a'。
-
另外还有三种绑定方式,分别是
self
parent
static
。-
self
是静态绑定,它的指向始终是在编译时所在的那个类。 -
parnet
也是静态绑定,它始终指向编译时所在类的父类,而这个父类是声明类时就指定了的,所以指向是明确的。 -
static
属于后期静态绑定,或者说是动态绑定或运行时绑定,它的指向与调用者有关。若调用者是所在类的实例,那么它就指向本类;若调用者是所在类子类的实例,它则指向子类。
-
2019.10.26 更新
如果想要通过 $b->test()
调用 B
的 foo
方法,可以将 A
中的 test
方法体改为 static::foo()
。因为存在如下定理:
当父类中的方法被子类调用时,方法中的$this->
会首先在其所在范围(代码上下文)里寻找私有方法或属性,如果寻找不到才会调用其子类的方法或属性。而static
属于后期静态绑定,它直接指向方法的调用者。
请仔细阅读官方文档:https://www.php.net/manual/en/language.oop5.late-static-bindings.php
B没有从A
继承
私有方法!继承是什么意思?我继承了,我就有了所有权,我可以使用并修改,这才是继承。使用就是调用,修改就是重写,缺任何一个都不叫继承。
那A的私有方法与B有什么关系呢?就是B只有使用权,并且只能通过A去使用它,只有这么一点关系。B既无法直接调用,也无法修改。
所以,官网是正确的,严谨的。网上的说法则是不严谨的。