Вызов методов потомка?
Модератор: Модераторы
Вызов методов потомка?
Народ всем привет!
Подскажите кто знает...
Каким образом, если вообще возможно, можно вызвать метод потомка, у объекта класса родителя, если у родителя этот метод вообще не объявлен?
Ну ,например, есть классы TMyClass0, а TMyClass1 - потомок. Создали объект obj1 класса TMyClass1, у него есть новый метод не объявленный в TMyClass0, допустим function show.
Затем переменной obj0 класса TMyClass0 присвоили объект obj1. Как вызвать show?
Подскажите кто знает...
Каким образом, если вообще возможно, можно вызвать метод потомка, у объекта класса родителя, если у родителя этот метод вообще не объявлен?
Ну ,например, есть классы TMyClass0, а TMyClass1 - потомок. Создали объект obj1 класса TMyClass1, у него есть новый метод не объявленный в TMyClass0, допустим function show.
Затем переменной obj0 класса TMyClass0 присвоили объект obj1. Как вызвать show?
возможно так
Код: Выделить всё
TMyClass1(obj0).show;
Если все твой код - применяй в родителе описание этого метода как abstract
tria писал(а):Если все твой код - применяй в родителе описание этого метода как abstract
Да код то мой, просто в класс родителя не зочетс\ вносить изменения ради такого, можно было конечно объявить его виртуальным и перекрыть в потомке и вызывать, а вот как без этого...
Интересно можно ли определить какого реально класса объект и в соответствии с этим вызвать метод этого класса?
хм... может имелось ввиду это:
Код: Выделить всё
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;
Не совсем , вроде бы...
Я наверное не особо понятно объясняю.
Допустим имеем класс-родитель, и не хотим менять его или добавлять новые методы к нему - Tparent. И имеем классы потомки этого класса. Допустим TChild, в которых прописаны новые методы. Затем в каком-то обработчике мы пишем создание объекта класса TChild
Функция CreateClass вызывает create указанного класса
Я наверное не особо понятно объясняю.
Допустим имеем класс-родитель, и не хотим менять его или добавлять новые методы к нему - 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;
dionic писал(а):Интересно можно ли определить какого реально класса объект
Код: Выделить всё
MyObject.ClassTypeДобавлено спустя 4 минуты 25 секунд:
Код: Выделить всё
var lobj: TParent; //по сути некоторый адрес
begin
lobj:= TChild.Create; //Выделили память для объекта с его методами
end;
далее где-то в обработчике:
TChild(lobj).show; //Вызываем дочерний метод (распределенный в памяти)
lobj.ParentMethod; //Вызываем собственные методы
Добавлено спустя 8 минут 26 секунд:
Только я не уверен, что не останется мусора в ОЗУ после FreeAndNil(lobj); Наверно лучше делать так:
Код: Выделить всё
TChild(lobj).free;
lobj := nil;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 и в соответствии с этим вызывать методы дочерних классов таким образом...
dionic писал(а):Можно конечно проверять ClassType и в соответствии с этим вызывать методы дочерних классов таким образом...
В принципе я так у себя и делаю. Подругому пока даже и не задумывался
Единственный минус в таком подходе - ограниченность классов. Но если пустить полностью все на самотек - это уже будет прототип Ии
Последний раз редактировалось VirtUX 27.05.2010 14:46:25, всего редактировалось 1 раз.
Ладно спасибо за ответы =)
Вместо проверки ClassType можно пользоваться операторами is и as.
Безопасный способ (если lobj не является TChild, ничего не произойдёт):
Опасный способ (если lobj не является TChild, будет Exception):
Во втором случае, если будет Exception, то он будет более понятный чем при просто TChild(lobj).show.
Безопасный способ (если lobj не является TChild, ничего не произойдёт):
Код: Выделить всё
if lobj is TChild then
TChild(lobj).show
Опасный способ (если lobj не является TChild, будет Exception):
Код: Выделить всё
(lobj as TChild).show
Во втором случае, если будет Exception, то он будет более понятный чем при просто TChild(lobj).show.
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.
Смысл в: определении процедурной переменной в родителе, для помещения туда (в некоторый момент времени) дочернего метода перед вызовом его из родителя.
VirtUX
Зачем городить такой огород?
Зачем городить такой огород?
Mr.Smart писал(а):Зачем городить такой огород?
А как проще?
Самый простой и правильный способ будет создание в родители данного только пустого, а в наследниках перекрывать его.
Если уж это никак не подходит, то делать как написал Odyssey
Если уж это никак не подходит, то делать как написал Odyssey
