private 继承中的 $this 问题

发布于 2022-09-03 14:50:04 字数 2623 浏览 22 评论 0

class base
{
    private $_var = 20;

    public function getVar()
    {
        echo $this->_var;
    }
}

class Ext extends base
{
    private $_var = 30;
}

$obj = new Ext();
$obj->getVar();

输出:20

之前提过一次这个问题:继承会拥有父类的 Private 属性和方法吗?,沙渺的回答也解答了疑惑,上面的代码也验证了这个解答。

但是,$this 的特性不是动态指定的吗?谁调用就指向谁,这里是 Ext 的对象调用的,虽然 getVar() 是基类的,但是按照 $this 的特性,不应该是指向 Ext 对象的吗?


2016-09-11 12:02,没人回答,试了下在基类中打印出 $this,分两种情况:

1、基类属性为 private

class base
{
    private $_var = 20;

    public function getVar()
    {
        var_dump($this);
        echo $this->_var;
    }
}

class Ext extends base
{
    protected $_var = 30;
}

$obj = new Ext();
$obj->getVar();

结果:

object(Ext)#1 (2) { ["_var":protected]=> int(30) ["_var":"base":private]=> int(20) } 20

2、基类的属性为 protected(也可以都为 public,总之希望被覆盖)

class base
{
    protected $_var = 20;

    public function getVar()
    {
        var_dump($this);
        echo $this->_var;
    }
}

class Ext extends base
{
    protected $_var = 30;
}

$obj = new Ext();
$obj->getVar();

结果:

object(Ext)#1 (1) { ["_var":protected]=> int(30) } 30

可以肯定的是:$this 确实指向的是 Ext 对象。

而之所以第二种情况输出了 30,看 dump 也很明显了,例子 2 中的 protected 属性被覆盖了,而 1 中的 private 得到了保留(private 默认是 final,无法被覆盖)。

所以这种现象是不是叫做“向上查找”(我自己杜撰的词)?因为 private 无法被覆盖,所以最终找到了父类的 var?

(事实上也没有合理的解释 $this 的问题)


2016-09-11 20:57

图片描述

图片描述

上面两图来自 Thinking in java,当创建子类时,与组合的显式创建不同,继承会隐含的在其内部创建一个基类对象。

这或许解释了 $this 的问题:

$this 是对 Ext 内存基址的引用,而此时基类的 Base 对象在其内部,再从 dump 出的结果,至少从表面上很好理解了,因为这个 $this 是写在 Base 对象中的,而 private 默认是 final 所以并不会被 override(dump 可以看到都得到了保留,Ext 中的 $_var 是个全新的属性)。

而当基类中的 $_var 为 protected / public 并且被子类覆盖时,不管“内含对象”的底层实现机制如何,至少从 dump 结果可以看到所谓的“覆盖”:基类的 $_var 已经不存在了,取而代之的是子类的 $_var,输出 30 也就很好理解了。

另外 stackoverflow 的同类问题:Behavior of $this on inherited methods
回答中提到的 “virtual method” 和 “lookup table” 概念也值得参考。


2016-09-12 20:34
JAVA 中this 和super与覆写冲突的问题?,甘明:java 版的解释。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

瑕疵 2022-09-10 14:50:04

这是不是覆盖不覆盖的问题,而是因为所使用的属性访问控制为private,getVar()方法就直接会找本类的属性,不会去检查继承链。

同样的,父类中访问控制为private的方法,如果通过其他父类的方法调用,即使在子类中也存在同名的方法,调用的方法也会使用父类原来的方法,不会管子类中的方法。

说简单点,private是不存在继承这么一说的。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文