Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

Алгоритм наследования PHP. Никак не пойму.

Сергей Яшановский Профи (530), закрыт 7 лет назад
Привет всем. У меня такой вопрос возник: может кто написать НОРМАЛЬНЫМ ЯЗЫКОМ, подробно, алгоритм наследования в PHP? Прост на всех сайтах пишется обычно одно и то же: "Наследование - это расширение существующего класса, при котором потомок может использовать не только свои свойства и методы, но и родителя (не все, учитываются модификаторы доступа)".

Мне это понятно, но вопрос у меня будет стоять глубже. Я делал много тестов с наследованием, и каждый раз входил в ступор и не понимал, почему именно так это работает. Вроде бы логически правильно, но понять алгоритм, по которому работает интерпретатор - не могу. То есть не пойму, КАК ИМЕННО работает наследование.

Рассмотрим пример:
class A {
private $k = 1;
public function check() {
return $this->k;
}
}

class B extends A {
public $k = 5;
}

$o = new B();
echo $o->check();

В данном коде программа выведет 1. Подумайте, почему (но я сам не до конца понимаю, вот и спрашиваю). Да, можно сказать, мол: "Ну, тут приватное свойство, оно не наследуется, поэтому метод check выводит свойство родителя со значением 1, а не 5 с потомка". НО. Если поставить метод в дочерний класс, убрав с родителя, то выведется 5. Вы, возможно, скажите: "Ну, тут просто метод находится в потомке, поэтому он в приоритет берет свойство, записанное в нем же, да и взять private он не может, так как тот не наследовался. Кроме того, свойство k в потомке здесь считается отдельным, никак не связанным со свойством родительского класса, так как, опять же, k не наследовался". Но смотрите: private не наследовался в двух вариантах, однако в 1 варианте выводится именно private свойство. На многих сайтах говорят, что при наследовании "копируется содержимое" из родительского класса в потомок, либо наоборот. Но если бы это было так, тогда private бы не скопировался, и программа в обоих случаях должна была бы выдать ответ 5. Но тут зависит от того, с какого класса вызывается метод. То есть, существуют определенные правила при наследовании, упоминание которых я пока не встречал на сайтах. В нашем примере можно предположить, что вызов чего-либо (в нашем случае $this->k) приоритетен там, в каком классе он был вызван. Тогда вроде все хорошо. Но заменим свойство родителя на public в коде выше. Теперь, получается, при вызове метода получится 1, однако это противоречит высказыванию выше про приоритет. Вы скажете, что свойство переопределилось: да, согласен. Но в какой момент? Когда создавался класс или объект? И как понять "переопределилось"? Значение в родителе изменилось? Или же родительское свойство "удалилось" (образно говорю, чтобы хоть как-то понимать принцип работы), а осталось только дочернее? Ну или оно осталось и там, и там, но в родителе просто изменилось значение? Или под этим словом вообще совсем другое понимают? Допустим, что это так. Но теперь удалим приватное свойство с родителя. Теперь в родителе не останется свойства k, и программа вызовет метод check, но по моей логике интерпретатор должен искать именно в этом классе значение, но он его не найдет, ведь оно в дочернем. Получается, что если не находятся где-либо нужные данные, то они ищутся в другом классе? Сначала в приоритетном - где был вызван - а потом в другом?

Мне кажется, что это не так, что я уже давным давно в рассуждениях ошибаюсь. Потому что это слишком запутанно и криво. И я хочу, чтобы хоть кто-нибудь мне объяснил, как именно всё это работает, это гребаное наследование. И да, попробуйте в программе, которую я написал выше, заменить доступы свойств родителя и наследника наоборот. Тогда программа выдаст ошибку с просьбой поставить дочернему классу public свойство. А почему так нельзя? И т. д., и т. п., и у меня мозги кипят. Помогите, пожалуйста.
Дополнен 7 лет назад
P.S. Вот в JS с прототипным наследованием всё просто, и я понял принцип его работы. А вот в PHP - нет.
Лучший ответ
Shah Мастер (1419) 7 лет назад
эх... попробую)
смотрите, в вашем примере имеем 2 класса. и сколько бы не было объектов, код классов будет только по одному экземпляру. А в создаваемых объектах формируются только свойства. И вы ошибаетесь, приоритетных классов нет. При создании объекта от класса В, в него копируются все свойства объекта А и сверху накладываются свойства класса В. В Вашем примере, от объекта А наследуется 1 приватное свойство в пространство имен класса А, в раздел приватного доступа для методов класса А. От объекта В 1 свойство в пространство имен класса В в раздел публичного доступа. Итого мы имеет 1 объект $o со свойствами $k = 1 в приватном разделе пространства класса А и $k=5 в публичном разделе пространства класса В.
Метод класса А прежде всего обращается к свойствам пространства имен класса А и если там находит приватное свойство, выдает сразу его, поскольку класс А точно знает, что приватное свойство не наследуется. И если мы в классе В определяем такое же свойство $k, то мы должны переписать метод, который обрабатывает это свойство. В случае наоборот, когда в классе А публичное свойство, а в классе В приватное, недопустимо. Ибо классу В доступны публичные разделы класса А и тут возникает конфликт, поскольку класс В уже знает о наличии публичного свойства родителя.
Вобщем, свойства хранятся в теле объекта, в разных пространствах имен, а методы лежат в загруженном коде класса.
Получилось как-то сумбурно конечно))
PuZZleМыслитель (7138) 7 лет назад
после прочтения у меня открылся третий глаз =))
Сергей ЯшановскийПрофи (530) 7 лет назад
Ого. Достойный ответ! Спасибо большое, а то уже голову сломал. И почему вы не пишите сайт со своим объяснением?) Было бы очень интересно почитать. Или же он есть? Если да, скиньте ссылку, пожалуйста :)
Shah Мастер (1419) Не за что) Мне самому не очень нравится мой ответ, писал сходу без особой подготовки) Сайт есть, но нет достойных тем. А писать все то, что уже написано многократно, не интересно
Сергей ЯшановскийПрофи (530) 7 лет назад
Ну или откуда Вы все это знаете? С сайта какого-то, книги или универ?
Shah Мастер (1419) Объектами интересовался еще с Turbo Pascal 5.5 для MS DOS))) Мне нравилось писать очереди, деревья и другие цепочки из объектов. Полноценно ООП изучал на Дельфи и затем до настоящего времени на PHP. К сожалению, изучал не профессионально, так на любительском уровне, по мере нужды в чем-либо.
Остальные ответы
Редис Александрович Оракул (77223) 7 лет назад
private свойство нельзя менять, оно наследуется, но только в режиме чтения, возможно надо установить тебе что бы он php варнинги выводил, там скорей всего напишит
Похожие вопросы