提问人:Jack Scandall 提问时间:3/20/2020 更新时间:3/20/2020 访问量:553
PHP:理解$this - 调用基类方法而不是子方法
PHP: understanding $this - calling base class method instead of child method
问:
在阅读 PHP.net 文档时,我偶然发现了一个问题,它扭曲了我理解$this的方式:
class C {
public function speak_child() {
//echo get_class($this);//D
echo $this->f();//calls method of C class... why?!
}
private function f() {
echo "C";
}
}
class D extends C {
public function speak_parent() {
echo $this->f();
}
public function f() {
echo "D";
}
}
$d= new D();
$d->speak_parent();
$d->speak_child();
由于$this是 D 类实例的表示形式,因此我期望输出:
DD
但是,实际输出是:
DC
为什么 $this->f() 宁愿访问基类方法,而不是子类方法? 当我们将 C->f 更改为公开时,情况会发生变化。
答:
1赞
Van Tho
3/20/2020
#1
因为 C 类的函数是私有的,所以不能被子类覆盖,子类不会看到它。因此,当您在子类中声明一个函数时,它是一个新函数,而不是从父类扩展而来的。f
f
如果将函数声明为在父类中,也可以扩展函数。f
protected
在此处编码为官方文档
声明为私有的成员只能由定义该成员的类访问。
评论
0赞
Jack Scandall
3/20/2020
这是否意味着,$this同时依赖于:1)对象的实例(新D())2)调用$this的范围?
0赞
Van Tho
3/20/2020
是的,$this是依赖的,只有函数,vars 是扩展的
1赞
El_Vanja
3/20/2020
#2
为什么 $this->f() 宁愿访问基类方法,而不是子类方法?
这就是设计。仔细想想,这是有道理的。通俗地说,继承就是关于常见的属性和方法。因此,最合乎逻辑的事情是从链的顶部开始 - 具有最常见方法/属性的级别(大多数是最高级的,而不是量词)。下面是简化的逻辑:
- 父类有方法吗?
- 如果没有,请检查子类。如果是,请检查可见性。
- 如果子项可以重写该方法,请检查它是否具有重写的方法。
- 如果没有,请运行 parent。如果是,请运行子项。
- 如果子项无法覆盖,请运行父项。
最后一点是你的例子的关键。父类不希望子类具有相同方法的实现。当你在父类中将一个方法声明为私有方法时,你是说子类没有处理这个问题的业务。因此,在子类中创建同名方法是没有意义的。如果子级需要使用它,则需要根据用例将该方法设为公共或受保护。
$this
始终表示所构造的类的实例。但是,您必须记住,子类既表示自身的实例,也表示父类的实例。方法和属性的使用将取决于上述逻辑。
评论