[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Как в PHP привести $this к базовому классу?
vasilisk
Пытаясь "сделать как правильно в ООП" обнаружил странное поведение PHP5, которое не понимаю, как можно обойти. А именно - если в базовом и в производном классе есть переменная с одинаковым именем, то по ссылке на производный класс доступен только тот экземпляр переменной, что определён в производном классе. Для ООП это - совершенно корректная ситуация, она разрешается указанием области видимости на которую распространяется ссылка на объект. К примеру, в С++ это могло бы выглядеть так:

class theA{
public:
int X = 3;

};

class theB : public theA{
public:
int X = 5;

};

Конструкторы и проч. здесь опущены, равно и как само присваивание сделано наглядно для краткости, но синтаксически неправильно. Я, в конце-концов, иллюстрирую проблему, найденную в PHP Если

class theA * ptrA = new theA();
class theB * ptrB = new theB();

то ptrA->X == 3, а ptrB->X == 5. При этом не запрещено и по указателю ptrB достучаться до того X, который равен 3. Надо только сказать, что ptrB следует считать указателем на theA. Это - совершенно корректно, поскольку theB - прямой наследник theA, делается это приведением типа: (theA)ptrB->X == 3, а ptrB->X как был, так и останется равным 5. Это - две разные переменные, они просто немного "затеняют" друг-друга, но не больше. Никаких проблем с пониманием к которой из них хочет обратиться программист у компилятора нет.

А вот в PHP такая штука не получается. Вот код:

<?php
class
theA{
var $class_data ='theA';

public function ShowData(){ print $this->class_data."\n"; }
public function ShowMyData(){ print $this->class_data."\n"; }
}


class theB extends theA{
var $class_data ='theB';

public function ShowData(){ print $this->class_data."\n"; }

}


$ObjA = new theA();
$ObjB = new theB();

$ObjA->ShowData(); //1
$ObjA->ShowMyData(); //2

$ObjB->ShowData(); //3
$ObjB->ShowMyData(); //4
?>

Код выводит:
theA //1
theA //2

theB //3
theB //4

Почему 1 и 3 строчки отличаются нет удивления - это разные классы и разные $this, а названия методов - одинаковые ShowData. Поэтому одинаковая конструкция print $this->class_data; и выводит разные результаты. Так - правильно и так и ожидается. А вот почему отличаются строчки 2 и 4 - тайна сия велика есть. Поскольку в классе theB нету метода ShowMyData, то совершенно правильно, что вызывается метод из класса theA - для theB класс theA базовый. Но вот почему у этого метода к классу theA не приводится и его $this, а подставляется $this от класса, про который theA ничего не знает? Ведь в методе theA::ShowMyData с точки зрения правильного ООП $this то должен быть от "своего класса" без лишних напоминаний? Нету здесь "виртуализации" - метод не перегружен, не объявлен виртуальным и проч.

Ладно, допустим, что в данном случае все методы и данные - виртуальные по умолчанию. Но тогда как синтаксически явно сделать "лишнее напоминание", что $this надо взять от theA? Очевидная конструкция (theA)$this не канает - это синтаксическая ошибка.

При этом внутри метода theB::ShowData можно вызывать theA::ShowData, это делается так:

public function ShowData(){
parent::ShowData();
print $this->class_data."\n";
}

и в этом случае сначала отработает конструкция print $this->class_data из theA::ShowData(), а следом - print $this->class_data из самого theB::ShowData(). Но $this в обе будет подставлен интерпретатором один и тот же, т.е. вывод этого метода будет:

theB
theB

Как достучаться до theA::$class_data имея ptrB?

Занятно, то если $class_data объявлен статическим, то никаких трудностей не возникает - есть и работает каст из "оператора четыре точки", причём такой всякий разный, что в голову не придёт его во всех вариантах использовать, коль скоро язык просто позволяет глобальные переменные. А как привести _нестатический_ $this?

Исследование "магических методов" показало, что это те же вариации на тему либо "статического каста", либо синтаксически кривого вызова всё тех же методов относительно "просто $this", т.е. извращения программиста, как сделать то, что не умеет компилятор. Но сколько я не искал я не нашёл ответа на вопрос в заголовке темы.

Я буду очень признателен коллегам за, как говорят any ideas - начиная от простой ликвидации моей дремучести и кончая извращениями, как этот самый каст эмулировать руками. Потому, как эта возможность - один из столпов ООП и без неё получается архитектурно криво.
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2025 Invision Power Services, Inc.