Наследование под капотом - PullRequest
       6

Наследование под капотом

6 голосов
/ 20 августа 2010

Итак, это последний вопрос ноющего наследства, который у меня возник немного, поэтому я хотел продолжить и задать вопрос. Поэтому я приведу пример на PHP:

<?php

class Base
{
    private $z = 4;


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

}

class Derived extends Base
{
}

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

$d->GetPrivate();

?>

Достаточно просто. Когда я всегда читал о наследовании, объяснение было просто «ты наследуешь публику и защищенных членов» и все. Чего я не понимаю, так это пары слов о том, как интерпретатор в этом примере показывает, что и к чему относится.

Например, когда я создаю производный класс, я могу использовать открытую функцию "GetPrivate" из Base для получения личных переменных базового класса. Однако, простое определение наследования не работает с этим для меня. Я имею в виду, что я наследую метод GetPrivate, но у меня все еще есть какая-то ссылка на приватные переменные только от того метода, который принадлежал базовому классу (хотя $ это относится к производному объекту класса). Я не смог создать новую функцию в классе Derived для доступа к этим закрытым переменным.

Таким образом, переводчик следит за тем, что было унаследованными функциями от базового класса, и возможными ссылками, которые они имеют на закрытые члены, доступные только этому базовому классу?

Ответы [ 3 ]

2 голосов
/ 20 августа 2010

Интерпретатор (или компилятор на другом языке ООП), проверяйте доступ по одному шагу за раз.

Когда вы вызываете $d->GetPrivate();, интерпретатор проверяет контекст в этом основном (публичный контекст, так как я предполагаю, что вы не в связанном классе с Drerived или Base), а GetPrivate() является публичным методом , Таким образом, $d->GetPrivate(); допускается в этом контексте, поэтому без ошибок.

В GetPrivate() контекстом является $d объект как Base, а доступ к z является частным элементом текущего объекта ($d). Таким образом, доступ действителен.

Понятие, которое здесь используется, - это «скрытие данных» (контроль доступа) и «инкапсуляция» (сочетание данных и функций).

Наследование только для воспроизведения позволяет использовать GetPrivate() из Base, поскольку оно принадлежит объекту Derived.

Это правда, что по-прежнему существует ссылка на личные данные, но эта ссылка не является прямой. Важность заключается в том, что доступ осуществляется как Base класс разрешен .

Итак, чтобы ответить на ваш вопрос:

ДА! Интерпретатор следит за тем, какие унаследованные функции были у базового класса, и за возможными ссылками, которые они имеют на закрытые члены, доступные только этому базовому классу.

Надеюсь, это поможет.

2 голосов
/ 20 августа 2010

Ответ прост: да, попробуйте это:

<?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();

Вы увидите, что теперь, когда мы определили getPrivate для класса Derived, мы больше не можем получить доступ к z вBase с момента его приватности, если мы хотим иметь доступ к нему из производного класса, нам нужно объявить его защищенным, а не приватным.

1 голос
/ 20 августа 2010

Ну, я не могу много рассказать о деталях синтаксического анализатора, но ключ к пониманию заключается в понимании того, что означает visibility :

Члены класса, объявленные общедоступными, доступны везде.Члены, объявленные защищенными, могут быть доступны только внутри самого класса и унаследованных и родительских классов.Члены, объявленные как частные, могут быть доступны только классу, который определил член.

Теперь в руководстве по PHP также указано :

Например, когда вы расширяете класс, подкласс наследует все открытые и защищенныеметоды из родительского класса.Если класс не переопределяет эти методы, они сохранят свою первоначальную функциональность.

Если вы выполните var_dump($d) для производного класса, вы увидите, что он содержит Base->z:

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

Таким образом, в Base есть ссылка на z, ноон является частным, и поскольку частный означает, что член может быть доступен только классу, который определяет член, вы не можете получить к нему доступ из Derived.

Предлагая публичные методы в Base для доступа к приватному члену, вы эффективно контролируете доступ через родительский метод.Возможно, $z - это то, что должно быть доступно только для чтения в расширенных классах, например, адаптер базы данных.

Это скрытие информации и контроль доступа.Это не значит, что если вы расширите Base, вы потеряете $ z.Наследование - это отношение is-a .Производное is-a Base и, как таковое, имеет $ z, хотя не само по себе, а через своего родителя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...