Страница 1 из 2
Вызов методов потомка?
Добавлено: 27.05.2010 13:46:01
dionic
Народ всем привет!
Подскажите кто знает...
Каким образом, если вообще возможно, можно вызвать метод потомка, у объекта класса родителя, если у родителя этот метод вообще не объявлен?
Ну ,например, есть классы TMyClass0, а TMyClass1 - потомок. Создали объект obj1 класса TMyClass1, у него есть новый метод не объявленный в TMyClass0, допустим function show.
Затем переменной obj0 класса TMyClass0 присвоили объект obj1. Как вызвать show?
Re: Вызов методов потомка?
Добавлено: 27.05.2010 13:49:16
Light13
Re: Вызов методов потомка?
Добавлено: 27.05.2010 13:55:07
tria
Если все твой код - применяй в родителе описание этого метода как abstract
Re: Вызов методов потомка?
Добавлено: 27.05.2010 13:59:30
dionic
tria писал(а):Если все твой код - применяй в родителе описание этого метода как abstract
Да код то мой, просто в класс родителя не зочетс\ вносить изменения ради такого, можно было конечно объявить его виртуальным и перекрыть в потомке и вызывать, а вот как без этого...
Интересно можно ли определить какого реально класса объект и в соответствии с этим вызвать метод этого класса?
Re: Вызов методов потомка?
Добавлено: 27.05.2010 14:01:14
VirtUX
хм... может имелось ввиду это:
Код: Выделить всё
type
mc1 = class
private
procedure MChild;
end;
mc2 = class(mc1)
public
procedure show;
end;
var
o: mc1;
procedure mc2.show;
begin
ShowMessage('yes');
end;
procedure mc1.MChild;
var
mc: mc2;
begin
mc := mc2.Create;
mc.show;
FreeAndNil(mc);
end;
begin
o.MChild;
end;
Re: Вызов методов потомка?
Добавлено: 27.05.2010 14:19:31
dionic
Не совсем , вроде бы...
Я наверное не особо понятно объясняю.
Допустим имеем класс-родитель, и не хотим менять его или добавлять новые методы к нему - Tparent. И имеем классы потомки этого класса. Допустим TChild, в которых прописаны новые методы. Затем в каком-то обработчике мы пишем создание объекта класса TChild
Функция CreateClass вызывает create указанного класса
Код: Выделить всё
type
Tparent = class
private
procedure MChild;
end;
TChild = class
public
function show;
end;
// где-то в обработчике ...
var lobj : Tparent;
begin
lobj:= CreateClass('имя класса потомка');
// вот потом необходимо вызвать метод show потомка который получился...
end;
Re: Вызов методов потомка?
Добавлено: 27.05.2010 14:35:00
VirtUX
dionic писал(а):Интересно можно ли определить какого реально класса объект
Добавлено спустя 4 минуты 25 секунд:Код: Выделить всё
var lobj: TParent; //по сути некоторый адрес
begin
lobj:= TChild.Create; //Выделили память для объекта с его методами
end;
далее где-то в обработчике:
TChild(lobj).show; //Вызываем дочерний метод (распределенный в памяти)
lobj.ParentMethod; //Вызываем собственные методы
Добавлено спустя 8 минут 26 секунд:Только я не уверен, что не останется мусора в ОЗУ после FreeAndNil(lobj); Наверно лучше делать так:
Re: Вызов методов потомка?
Добавлено: 27.05.2010 14:40:01
dionic
VirtUX писал(а):Добавлено спустя 4 минуты 25 секунд:Код: Выделить всё
var lobj: TParent; //по сути некоторый адрес
begin
lobj:= TChild.Create; //Выделили память для объекта с его методами
end;
далее где-то в обработчике:
TChild(lobj).show; //Вызываем дочерний метод (распределенный в памяти)
lobj.ParentMetoth; //Вызываем собственные методы
Ну вы всё правильно пишете но только для частного случая, у меня просто функция CreateClass вызывает конструкторы классов потомков TParent и возвращает эти объекты. Т.е. lobj:= TChild.Create; - это частный случай, CreateClass('имя класса') - общий, я туда передаю название класса потомка Tparent.
И поэтому потом я не знаю как вызвать метод потомка, т.к. у меня lobj класса TParent. Хотя когда идет отладка он TChild.
Но написать TChild(lobj).show я не могу , т.к какой конкретно класс сейчас я не знаю...
Можно конечно проверять ClassType и в соответствии с этим вызывать методы дочерних классов таким образом...
Re: Вызов методов потомка?
Добавлено: 27.05.2010 14:42:56
VirtUX
dionic писал(а):Можно конечно проверять ClassType и в соответствии с этим вызывать методы дочерних классов таким образом...
В принципе я так у себя и делаю. Подругому пока даже и не задумывался

Единственный минус в таком подходе - ограниченность классов. Но если пустить полностью все на самотек - это уже будет прототип Ии

Ведь методы дочерних тоже могут быть непредсказуемые...
Re: Вызов методов потомка?
Добавлено: 27.05.2010 14:46:14
dionic
Ладно спасибо за ответы =)
Re: Вызов методов потомка?
Добавлено: 27.05.2010 15:30:51
Odyssey
Вместо проверки ClassType можно пользоваться операторами
is и
as.
Безопасный способ (если lobj не является TChild, ничего не произойдёт):
Опасный способ (если lobj не является TChild, будет Exception):
Во втором случае, если будет Exception, то он будет более понятный чем при просто TChild(lobj).show.
Re: Вызов методов потомка?
Добавлено: 27.05.2010 18:12:51
VirtUX
Odyssey писал(а):Вместо проверки ClassType можно пользоваться операторами is и as.
В любом случае - это не решает проблему.
Мне тут пришла мысль в голову, а если так:
Код: Выделить всё
type
TObjProcedure = procedure of object;
{Родитель}
TAnyParent = class
property ChildMethod: TObjProcedure;
procedure {или function} CreateClass(Sender: TObject);
end;
{Дочерний}
TChild = class(TAnyParent)
procedure AnyChildMethod;
constructor Create;
end;
{Переменные}
var
PrObj = TAnyParent;
implementation
{Некоторая процедура}
procedure AnyProc;
begin
if PrObj.ChildMethod <> nil then PrObj.ChildMethod; //Вызов дочернего метода
end;
constructor TChild.Create;
begin
inherited Create;
ChildMethod := @AnyChildMethod; //Это же можно делать и по любому событию в дочернем классе - не только при создании.
end;
end.
Смысл в: определении процедурной переменной в родителе, для помещения туда (в некоторый момент времени) дочернего метода перед вызовом его из родителя.
Re: Вызов методов потомка?
Добавлено: 27.05.2010 19:44:50
Mr.Smart
VirtUX
Зачем городить такой огород?
Re: Вызов методов потомка?
Добавлено: 27.05.2010 19:52:43
VirtUX
Mr.Smart писал(а):Зачем городить такой огород?
А как проще?
Re: Вызов методов потомка?
Добавлено: 27.05.2010 19:59:00
Mr.Smart
Самый простой и правильный способ будет создание в родители данного только пустого, а в наследниках перекрывать его.
Если уж это никак не подходит, то делать как написал Odyssey