Наследование PHP, родительские функции с использованием дочерних переменных - PullRequest
14 голосов
/ 15 марта 2012

При просмотре кода PHP я обнаружил странную вещь. Вот простая иллюстрация этого примера:

Файл A.php:

<?php
class A{
    public function methodA(){
        echo $this->B;
    }
}
?>

Файл B.php:

<?php
    class B extends A{
        public $B = "It's working!";
    }
?>

Файл test.php:

<?php
    require_once("A.php");
    require_once("B.php");
    $b = new B();
    $b->methodA();
?>

Запуск test.php выводит «Это работает!», Но вопрос в том, почему он работает? :) Это фича или ошибка? Метод methodA в классе A также может вызывать методы из класса B, которые не должны работать в ООП.

Ответы [ 8 ]

12 голосов
/ 15 марта 2012

Вы только экземпляр класса B. Проигнорируйте A на данный момент и сделайте вид, что methodA() является частью класса B.

Когда класс B расширяет A, он получает все функции A. $this->B не оценивается, пока не запущен код, а не предыдущий. Поэтому ошибка не возникает и не будет возникать, поскольку $this->B существует в классе B.

6 голосов
/ 15 марта 2012

PHP - динамический язык.Методы и члены данных оцениваются во время выполнения.Когда вы вызываете метод или обращаетесь к члену, PHP фактически ищет хеш-таблицу своего рода, чтобы выяснить, можно ли получить доступ к этому методу или члену для этого объекта или нет, что может быть где-нибудь в иерархии наследования.

Ине только наследование, вы всегда можете назначить произвольные данные объекту во время выполнения, и код внутри класса все равно сможет получить к нему доступ, используя $ this-> что-то, где «что-то» даже не существует в классе.

3 голосов
/ 16 марта 2012

$this - это просто переменная объекта - особая, потому что она является текущей, но она все еще является просто переменной объекта.

Поскольку $B::B является общедоступной переменной-членом, к ней можно получить доступиз любого места доступна ссылка на экземпляр B, например, с помощью переменной объекта.

Поскольку открытые члены доступны везде, к любой функции, даже из A::methodA(), можно получить доступ.

Так что тут не о чем удивляться.Наследование классов в вашем примере относится только к (невидимой) передаче объектной переменной в виде $this «параметра» при вызове A::methodA().

См. Следующий пример, который, вероятно, делает его более видимым:

function methodA($object) {
    echo $object->B;
}

class B {
    public $B = "It's working!";
    public function methodA() {
        methodA($this);
    }
}
2 голосов
/ 15 марта 2012

Поскольку PHP является динамическим языком, нет ничего плохого в том, чтобы вызывать свойства или методы, которые могут существовать в экземпляре, который его использует (в данном случае экземпляр подкласса B)

1 голос
/ 15 марта 2012

Вот как ООП должен работать. Поначалу это может показаться немного странным, поскольку вы думаете, что A должен знать, что такое $this->B первым (и действительно, в некоторых языках это выдает предупреждение компилятора), но поведение правильное, так как подкласс ' Повторное использование определяет переменную, которую ищет ваша функция. Если вы вызвали methodA() из экземпляра A(), вы получите «неопределенную» ошибку.

Теперь, что было бы странно (читай: неправильно ), если ЭТО сработало:

class A {
   public $b = "Derp";
}
class B extends A {
  function sayIt() { echo $this->b; }
}
$a = new A();
$a->sayIt();
1 голос
/ 15 марта 2012

Это имеет смысл для меня;$ B становится доступным в результирующем объекте благодаря его появлению в классе B. Так как $ this-> B вычисляется во время выполнения, и значение устанавливается до этого (когда создается экземпляр класса B), оказывается, что оноустановить правильно.

Вы можете сделать это и с методами, так как их существование не проверяется до тех пор, пока они не будут выполнены (хотя в случае методов обычно объявляют их абстрактными в родительском классе, что вызываетребенок для их реализации).

1 голос
/ 15 марта 2012

PHP - динамический язык. Когда метод A () вызывается для экземпляра B, член B $ B действительно существует.

$a = new A();
$a->methodA();

не будет работать.

В некоторых динамических языках вы даже можете определять методы во время выполнения.

0 голосов
/ 15 марта 2012

Класс B расширяется от класса A, следовательно, он наследует метод methodA() от класса A.

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