PHP и иерархия классов

AKoval

Guest
PHP и иерархия классов

Уважаемые профессионалы!
Кто-нибудь может подсказать, где собака зарыта?
Есть иерархия классов следующего вида:
class baseDB(){
function baseDB($objectID){
. . . .
$this->Refresh();
}
function Refresh(){
. . . .
}
}

class Client extends baseDB(){
function Client($clientID){
. . . .
parent::baseDB($clientID);
}
function Refresh(){
. . . .
parent::Refresh();
. . . .
}
}

class pClient extends Client(){
function pClient($pClientID){
. . . .
parent::Client($pClientID);
. . . .
}
function Refresh(){
. . . .
parent::Refresh();
. . . .
}
}
class cClient extends Client(){
function cClient($cClientID){
. . . .
parent::Client($cClientID);
}
function Refresh(){
. . . .
parent::Refresh();
. . . .
}
}

$obj = new pClient('000000001');
или
$obj = new cClient('000000002');

Проблема: когда я создаю объект класса pClient все нормально, когда же созжаю объект класса cClient почему-то в конструкторе класса baseDB на вызове $this->Refresh() происходит что-то непонятное. Такое впечатление, что в этом месте работа прекращается и управление передается следующей за new команде без всяких сообщений и ошибок. Хотя я повставлял после каждого обращения к Refresh отладочные печати, никаких результатов не вижу.
Как только в классе baseDB комментирую $this->Refresh() - все отрабатывает нормально. Точно так же все работает, если заменяю только в этом классе Refresh на fresh например. Я конечно не считаю себя большим специалистом в ООП, но это для меня не понятно.
Естественно, что в методах Refresh классов-потомков что-то делается дополнительно, и возможно, что именно в этом причина всего, но как ее найти?
Может кто-нибудь хотя бы подсказать, в чем дело и с какого конца это все разбирать?
Спасибо.
 

AKoval

Guest
Дополнительная информация:
Когда я в классе baseDB заменил $this->Refresh(); на baseDB::Refresh(); все заработало, но ведь и в изначальном виде должно работать (и работает в некоторых случаях).
Глюк?
 

AKoval

Guest
Функцию Refresh я не заново определяю.
В каждом производном классе она делает чуть больше, чем в предидущем.
Например, в baseDB эта функция вычитывает из базы данных запись с заданным ключем. Т.е. эта операция выполняется всегда, когда я создаю объект для записи из какой-то таблицы.
Далее, если это например таблица клиентов, в зависимости от того, какой это клиент - корпоративный или частное лицо, я имею либо просто контактную информацию (ФИО,адрес, телефоны и т.д), либо список лиц для контакта (примерно то же самое, что и в предидущем случае, но возможно во множественном числе).
Вот поэтому, я имею два класса для такого типа клиентов. При этом базовая информация по клиенту всегда читается в методе Refresh класса baseDB, а все особенности учитываются в методах Refresh в классах-потомках.
Аналогично и с обновлением записи в базе данных.
На уровне пользователя я же работаю с объектом типа клиент, а не с записями.
 

kim

Guest
Автор оригинала: AKoval
Дополнительная информация:
Когда я в классе baseDB заменил $this->Refresh(); на baseDB::Refresh(); все заработало, но ведь и в изначальном виде должно работать (и работает в некоторых случаях).
Глюк?
В классе cClient есть методы:
cClient::Refresh()
Client::Refresh()
baseDB::Refresh()
Для реализации данного класса (объекта) $this->Refresh() есть тоже самое, что и cClient::Refresh()
Намек понятен?
 

kvn

programmer
когда же созжаю объект класса cClient почему-то в конструкторе класса baseDB на вызове $this->Refresh() происходит что-то непонятное. Такое впечатление, что в этом месте работа прекращается и управление передается следующей за new команде без всяких сообщений и ошибок.
Можно вот это поподробней..?
 

AKoval

Guest
Если я правильно понимаю, то у меня должна выполнятся следующая последовательность:
В cClient::Refresh() ---->parent::Refresh() - это в Client::Refresh() и далее parent::Refresh() - это в baseDB::Refresh().
Ведь в каждом методе я вызываю такой же метод родительского класса.
По крайней мере в С++ это так работало.
 

Crazy

Developer
Есть мнение, что семантика "parent::" в PHP кардинально отличается от таковой с C++ и стоит попробовать явно указать имя класса вместо parent...
 

kvn

programmer
Есть мнение, что семантика "parent::" в PHP кардинально отличается от таковой с C++ и стоит попробовать явно указать имя класса вместо parent...
А про это мнение можно прочитать..? где-нибудь...?
 

Crazy

Developer
"Есть мнение" эквивалентно "был слух". В подробности я не вдавался.

В нашем же случае клюки вероятнее всего исходят из другого: Refresh потомка выполняется ДО того, как будет до конца исполнен конструктор потомка. Если в конструкторе был инициализационный код, необходимый для выполнения Refresh, то весьма вероятны глюки.

Вообще, выполнение активных действий в конструкторе есть определенно дурной тон...
 

Barlone

Guest
Автор оригинала: AKoval
Дополнительная информация:
Когда я в классе baseDB заменил $this->Refresh(); на baseDB::Refresh(); все заработало, но ведь и в изначальном виде должно работать (и работает в некоторых случаях).
Глюк?
В PHP все функции виртуальные (в терминах С++).
Так что в классе baseDB $this->Refresh() и baseDB::Refresh() не одно и то же, если вызов был из класса-потомка.
 

kvn

programmer
PHP:
class baseDB {
    function baseDB($objectID){
    echo 'baseDB::baseDB<br>';
    $this->Refresh();
    }

    function Refresh(){
    echo 'baseDB::Refresh<br>';
    }
}

class Client extends baseDB{
    function Client($clientID){
    echo 'Client::Client<br>';
    parent::baseDB($clientID);
    }

    function Refresh(){
    echo 'Client::Refresh<br>';
    parent::Refresh();
    }
}
class pClient extends Client {
    function pClient($pClientID){
    echo 'pClient::pClient<br>';
    parent::Client($pClientID);
    }

    function Refresh(){
    echo 'pClient::Refresh<br>';
    parent::Refresh();
    }
}
class cClient extends Client{
    function cClient($cClientID){
    echo 'cClient::cClient<br>';
    parent::Client($cClientID);
    }
    function Refresh(){
    echo 'cClient::Refresh<br>';
    parent::Refresh();
    }
}

$obj = new pClient('000000001');
echo '<hr>';
$obj = new cClient('000000002');
Имеем:

pClient::pClient
Client::Client
baseDB::baseDB
pClient::Refresh
Client::Refresh
baseDB::Refresh

--------------------------------------------------------------------------------
cClient::cClient
Client::Client
baseDB::baseDB
cClient::Refresh
Client::Refresh
baseDB::Refresh

:)
 

Crazy

Developer
Здесь отладочная печать стоит не после обращения к конструектору базового класса (где обычно стоит дополнительный код конструктора производного класса), а ДО него. :) Обрати внимание, что судя по данному списку классы иниципализируются от последнего потомка к предку. Что явно неестественно.

Если поставить на должное место -- получится именно описанная мной картина:

Код:
baseDB:: baseDB
baseDB:: Refresh
Client:: Refresh
pClient:: Refresh
Client:: Client
pClient:: Client
 

kvn

programmer
Если поставить на должное место
Да.
вот:
PHP:
class baseDB {
    function baseDB($objectID){
    echo 'baseDB::baseDB<br>';
    $this->Refresh();
    }

    function Refresh(){
    echo 'baseDB::Refresh<br>';
    }
}

class Client extends baseDB{
    function Client($clientID){
    parent::baseDB($clientID);
    echo 'Client::Client<br>';
    }

    function Refresh(){
    parent::Refresh();
    echo 'Client::Refresh<br>';
    }
}
class pClient extends Client {
    function pClient($pClientID){
    parent::Client($pClientID);
    echo 'pClient::pClient<br>';
    }

    function Refresh(){
    parent::Refresh();
    echo 'pClient::Refresh<br>';
    }
}
class cClient extends Client{
    function cClient($cClientID){
    parent::Client($cClientID);
    echo 'cClient::cClient<br>';
    }
    function Refresh(){
    parent::Refresh();
    echo 'cClient::Refresh<br>';
    }
}

$obj = new pClient('000000001');
echo '<hr>';
$obj = new cClient('000000002');
Код:
baseDB::baseDB
baseDB::Refresh
Client::Refresh
pClient::Refresh
Client::Client
pClient::pClient

--------------------------------------------------------------------------------
baseDB::baseDB
baseDB::Refresh
Client::Refresh
cClient::Refresh
Client::Client
cClient::cClient
 
Сверху