Intereting Posts

Наследование PHP, родительские функции с использованием дочерних переменных

При просмотре кода 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, которые не должны работать в ООП.

Solutions Collecting From Web of "Наследование PHP, родительские функции с использованием дочерних переменных"

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

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

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

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

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

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

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

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

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

 function methodA($object) { echo $object->B; } class B { public $B = "It's working!"; public function methodA() { methodA($this); } } 

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

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

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

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

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

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

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

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

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

 class A { public $b = "Derp"; } class B extends A { function sayIt() { echo $this->b; } } $a = new A(); $a->sayIt(); 

Класс B распространяется от класса A, поэтому он наследует метод метода methodA() из класса A.