Наследование PHP, родительские функции с использованием дочерних переменных
При просмотре кода PHP я обнаружил странную вещь. Вот его простой пример:
Файл A.php:
<?php
class A{
public function methodA(){
echo $this->B;
}
}
?>
Файл B.php:
<?php
class B extends A{
public $B = "It working!";
}
?>
Файл test.php:
<?php
require_once("A.php");
require_once("B.php");
$b = new B();
$b->methodA();
?>
Запуск test.php выводит "Это работает!", но вопрос в том, почему он работает?:) Является ли это признаком или ошибкой? Метод methodA в классе A также может вызывать методы, которые находятся в классе B, которые не должны работать в ООП.
Ответы
Ответ 1
Вы создаете экземпляр класса B
. Игнорируйте A
на данный момент и притворитесь, что methodA()
является частью класса B
.
Когда класс B
extends A
, он получает все функции A
. $this->B
не оценивается до тех пор, пока код не будет запущен, а не ранее. Поэтому ошибка не возникает и не будет встречаться как $this->B
существует в классе B
.
Ответ 2
PHP - это динамический язык. Методы и элементы данных оцениваются во время выполнения. Когда вы вызываете метод или получаете доступ к члену, PHP на самом деле ищет хэш-таблицу сортировки, чтобы выяснить, доступен ли этот метод или член на этом объекте или нет, что может быть где угодно в иерархии наследования.
И не только наследование, вы всегда можете назначать произвольные данные объекту во время выполнения, а код внутри класса по-прежнему сможет получить к нему доступ, используя $this- > нечто, где "что-то" даже не существует в классе.
Ответ 3
$this
- это просто объектная переменная - специальная, потому что она является текущей, но она все еще является только переменной объекта.
Поскольку $B::B
является переменной открытого участника, к ней можно получить доступ из вездесущей, где ссылка на экземпляр B
достижима, например. с переменной объекта.
Поскольку публичные члены доступны повсюду, любая функция, даже изнутри A::methodA()
, может быть доступна.
Значит, на самом деле не о чем беспокоиться. Наследование класса в вашем примере относится только к (невидимой) передаче объектной переменной в форме параметра $this
"при вызове A::methodA()
.
См. следующий пример, который, вероятно, делает его более заметным:
function methodA($object) {
echo $object->B;
}
class B {
public $B = "It working!";
public function methodA() {
methodA($this);
}
}
Ответ 4
Поскольку PHP является динамическим языком, нет ничего плохого в том, что вызывающие свойства или методы могут существовать в экземпляре, который его использует (в данном случае экземпляр подкласса B)
Ответ 5
PHP - это динамический язык. Когда методA() вызывается в экземпляре B, член B B фактически существует.
$a = new A();
$a->methodA();
не работает.
В некоторых динамических языках вы можете даже определять методы во время выполнения.
Ответ 6
Это имеет смысл для меня; $B становится доступным в результирующем объекте в силу его появления в классе B. Поскольку $this- > B оценивается во время выполнения, и значение устанавливается перед этим (когда экземпляр класса B создается), оказывается, что правильно установить.
Вы можете сделать это также с помощью методов, поскольку их существование не проверяется до тех пор, пока они не будут выполнены (хотя обычно в случае методов объявлять их абстрактными в родительском классе, тем самым вынуждая ребенка реализовать их).
Ответ 7
Вот как должен работать ООП. Сначала это может показаться немного странным, так как вы думаете, что A должен знать, что $this->B
является первым (и действительно, на некоторых языках это создаст предупреждение компилятора), но поведение правильное, так как подкласс, re use определяет переменную, которую ищет ваша функция. Если вы вызвали methodA()
из экземпляра A()
, вы получили бы ошибку "undefined".
Теперь, что было бы странно (читайте: неверно), если ЭТО работает:
class A {
public $b = "Derp";
}
class B extends A {
function sayIt() { echo $this->b; }
}
$a = new A();
$a->sayIt();
Ответ 8
Класс B продолжается от класса A, поэтому он наследует метод methodA()
из класса A.