Страница 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
возможно так
Код: Выделить всё
  TMyClass1(obj0).show;

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:22:09
VirtUX
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;

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, ничего не произойдёт):
Код: Выделить всё
if lobj is TChild then
  TChild(lobj).show

Опасный способ (если lobj не является TChild, будет Exception):
Код: Выделить всё
(lobj as TChild).show

Во втором случае, если будет 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