【问题标题】:Inheritance under the hood引擎盖下的继承
【发布时间】:2011-04-01 13:50:17
【问题描述】:

所以,这是我最近遇到的最后一个令人烦恼的继承问题,所以我想继续问下去。所以我将在PHP中举一个例子:

<?php

class Base
{
    private $z = 4;


    function GetPrivate()
    {
        echo $this->z;
    }

}

class Derived extends Base
{
}

$b = new Base();
$d = new Derived();

$d->GetPrivate();

?>

足够简单。当我一直阅读有关继承时,解释只是“您继承了公共和受保护的成员”,仅此而已。我没有得到的是关于这个例子中的解释器如何确定什么属于什么的一些事情。

例如,在创建派生类时,我可以使用 Base 的公共函数“GetPrivate”获取基类的私有变量。但是,继承的简单定义不适用于我。我的意思是,我继承了 GetPrivate 方法,但我仍然有某种链接到私有变量,只是从属于基类的那个方法(即使 $this 指的是派生类对象)。我无法在 Derived 类中创建新函数来访问这些私有变量。

因此,解释器是否密切关注从基类继承的函数以及它们与仅对该基类可用的私有成员的可能链接?

【问题讨论】:

    标签: php inheritance


    【解决方案1】:

    答案很简单,试试这个:

    <?php
    
    
    class Base
    {
        private $z = 10;
    
        public function getPrivate()
        {
            return $this->z;
        }
    }
    
    
    class Derived extends Base
    {
        public function getPrivate()
        {
            return $this->z;
        }
    }
    
    $a = new Derived();
    
    echo $a->getPrivate();
    

    您会看到,既然我们已经在Derived 类上定义了getPrivate,我们就不能再在Base 中访问z,因为它是私有的,如果我们希望能够从派生类访问它类,我们需要将其声明为受保护而不是私有。

    【讨论】:

      【解决方案2】:

      解释器(或其他 OOP 语言的编译器),一次检查访问。

      当您调用 $d-&gt;GetPrivate(); 时,解释器检查 this 中的上下文是主要的(公共上下文,因为我假设您不在与 DrerivedBase 相关的类中)并且 GetPrivate() 是一个公共方法.因此,$d-&gt;GetPrivate(); 在此上下文中是允许的,因此不会出错。

      GetPrivate() 中,上下文是$d 对象Base,对z 的访问是当前对象($d) 的私有元素。因此访问是有效的。

      这里用到的概念是“数据隐藏”(访问控制)和“封装”(数据和功能的结合)。

      仅允许使用BaseGetPrivate() 的继承,因为它属于Derived 的对象。

      确实存在指向私有数据的链接,但该链接不是直接链接。重要的是访问发生在Base 类允许

      所以回答你的问题是:

      是的! 解释器密切关注从基类继承的函数以及它们与仅对该基类可用的私有成员的可能链接。

      希望这会有所帮助。

      【讨论】:

        【解决方案3】:

        好吧,我不能说太多关于解析器的细节,但理解的关键是理解visibility 的含义:

        声明为 public 的类成员可以在任何地方访问。声明为受保护的成员只能在类本身内以及被继承类和父类访问。声明为私有的成员只能由定义该成员的类访问。

        Now, the PHP manual also states:

        例如,当您扩展一个类时,子类会继承父类的所有公共和受保护方法。除非一个类覆盖这些方法,否则它们将保留其原始功能。

        如果您对派生类执行var_dump($d),您将看到它包含Base-&gt;z

        object(Derived)#2 (1) {
          ["z":"Base":private]=>
          int(4)
        }
        

        所以 Base 中有对 z 的引用,但它是私有的,并且由于私有意味着该成员只能由定义该成员的类访问,因此您无法从 Derived 访问它。

        通过在 Base 中提供公共方法来访问私有成员,您可以通过父方法有效地控制访问。也许$z 在扩展类中必须是只读的,例如数据库适配器。

        这是信息隐藏和访问控制。这并不意味着,如果你扩展 Base,你将失去 $z。继承是一种is-a 关系。派生的 is-a 基,因此,它有一个 $z,虽然不是在其自身上,而是通过它的父级。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-03
          • 1970-01-01
          • 1970-01-01
          • 2015-09-27
          相关资源
          最近更新 更多