Вызов методов потомка?

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Re: Вызов методов потомка?

Сообщение скалогрыз » 27.05.2010 19:59:52

dionic писал(а):Народ всем привет!
Подскажите кто знает...
Каким образом, если вообще возможно, можно вызвать метод потомка, у объекта класса родителя, если у родителя этот метод вообще не объявлен?

если такая необходимость возникла - нужно срочно поменять логику структуры данных. (частный случай этого решения - вынести метод в родительский класс).

я знаю кучу хороших программ (например fp-компилятор и Лазарус), написанных на паскале, которые успешно работают, без этаких извращений. А всё почему - правильное использование ООП :)

"как легче вкручивать шурупы молотком?!"
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Вызов методов потомка?

Сообщение VirtUX » 27.05.2010 20:12:54

Mr.Smart писал(а):Самый простой и правильный способ будет создание в родители данного только пустого, а в наследниках перекрывать его.

Извиняюсь за ламерство. А как (этот пустой) потом вызывать в родительском? А если этих методов несколько (в дочернем)? И если неизвестно заранее сколько этих методов (дочерних) нужно будет вызвать в родительском?
Просто у меня похожая ситуация, но пока кода мало я решаю проблему топором (по типу как тут уже писал). За разжевывание - отдельная благодарочка.
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Вызов методов потомка?

Сообщение and » 27.05.2010 20:53:07

Ну, ещё можно в сторону GetMethodProp посмотреть.
Аватара пользователя
and
постоялец
 
Сообщения: 124
Зарегистрирован: 16.09.2009 17:11:01
Откуда: г. Гомель, Беларусь

Re: Вызов методов потомка?

Сообщение Odyssey » 28.05.2010 00:04:13

VirtUX писал(а):property ChildMethod: TObjProcedure;

Это те же обработчики событий, типа TButton.OnClick, которые используется во всех LCL/VCL контролах. Проверено временем, правда используется в основном там, где нужно устанавливать нужный метод извне.

VirtUX писал(а):А как (этот пустой) потом вызывать в родительском?

Прямо так и вызывать, именно для этого и существуют виртуальные методы. Надеюсь, никого не обижу если напомню основную фишку виртуальных методов:
Код: Выделить всё
TParent = class
  procedure ChildMethod; virtual; // пустой, если лень писать begin end;
                                  // можно написать abstract; после virtual.
end;

TChild = class(TParent)
  procedure ChildMethod; override;
end;

Теперь если сделать так:
Код: Выделить всё
var
  obj: TParent;
begin
  obj := TChild.Create;
  obj.ChildMethod();
  FreeAndNil(obj);
end;

То будет вызван именно TChild.ChildMethod, несмотря на то, что переменная типа TParent. Это потому, что метод определяется не по объявленному в var типу, а по реально созданному, т.е. чей конструктор мы вызывали. Виртуальные методы сделаны именно для описываемой цели. Другое дело, что топикстартер, зная об этом, почему то сознательно не хотел этот способ использовать, о чём и предупредил. Поэтому ему я не предлагал.

VirtUX писал(а):А если этих методов несколько (в дочернем)?

Можно создавать для каждого виртуальный метод в родителе, а можно вообще отказаться от такого наследования. Наследование по сути -- лишь способ повторного использования функциональности без дублирования кода. Если у потомков одного родителя настолько разная функциональность, что не хочется объединять её в родителе, то может и ну его?

VirtUX писал(а):И если неизвестно заранее сколько этих методов (дочерних) нужно будет вызвать в родительском?
Если неизвестно на этапе проектирования родителя, т.е. родитель после окончания и заморозки своего кода должен будет вызывать произвольное количество неизвестных ему методов, то наверное только на основе списка таких обработчиков, которые вы описали несколькими постами выше.

Вообще, есть две мысли:
1) Реальный пример лучше бы помог найти хорошее решение. Пока мы рассуждаем на TParent и TChild со стороны всё кажется элементарным, логично решающимся с помощью виртуальных методов.
2) Оффтоп: для случаев, когда "заранее неизвестно", у кого, чего и сколько вызвать, Pascal -- не самый эффективный язык. Строгая типизация и проверки до рантайма помогают ловить ошибки, но это иногда здорово связывает руки. Возможно для таких частей системы стоит взглянуть на что-нибудь динамическое, типа Lua.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Вызов методов потомка?

Сообщение dionic » 28.05.2010 08:41:00

Odyssey спасибо ,конечно, за разъяснение виртуальных методов=), это было самое очевидное решение, и оно у меня сейчас и применено.
Я просто думал, что возможно найдётся какой-то обход данного случая... Постараюсь привести сегодня реальный пример кода... Просто незнаю насколько это получится...
dionic
новенький
 
Сообщения: 90
Зарегистрирован: 17.06.2009 21:00:08

Re: Вызов методов потомка?

Сообщение VirtUX » 28.05.2010 10:43:19

Odyssey писал(а):var
obj: TParent;
begin
obj := TChild.Create;

Вот это, как писал dionic, подходит для частного случая. Т.е. мы заранее знаем, с каким дочерним классом работаем. Но если класс создан
Код: Выделить всё
obj := TParent.Create;
и нужно вызвать метод дочернего (может TChild, а может и TChild2) класса, то это не прокатит.
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Вызов методов потомка?

Сообщение dionic » 28.05.2010 10:46:19

Почему не прокатит, всё прокатит с виртуальными методами , у меня прокатывает же. Вопрос как раз в том как сделать тоже самое но что бы не трограть родителя , т.е. не добавлять виртуальных методов ему и не перекрывать их в потомках...=)

На самом деле obj просто объявлен как TParent, а на этапе работы он TChild.
dionic
новенький
 
Сообщения: 90
Зарегистрирован: 17.06.2009 21:00:08

Re: Вызов методов потомка?

Сообщение Odyssey » 28.05.2010 11:48:56

VirtUX писал(а):Но если класс создан
Код: Выделить всё
obj := TParent.Create;
и нужно вызвать метод дочернего (может TChild, а может и TChild2) класса, то это не прокатит.

Да, в этом случае не прокатит ничего из вышеупомянутого, кроме обработчиков событий. Ведь методов этих у парента просто нет. И слово "дочерний" в данном случае ни к чему не обязывает, с тем же успехом можно пытаться у класса A вызвать методы независимого от него класса B. При наследовании только дочерние классы знают о родителях и могут повторно использовать их код, а родительские классы ничего не знают о дочерних. В зависимости от конкретного случая, можно попробовать "вывернуть" иерархию (т.е. обратить цепочку наследования), или использовать интерфейсы.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Вызов методов потомка?

Сообщение Timid » 28.05.2010 16:43:15

Вообще-то для этого есть понятие виртуального метода. Ключевое слово virtual.
Метод определенный как виртуальный можно не описывать в родителе, всегда будет вызываться последний перекрытый метод. Даже при использовании inherited для вызова родительского метода (в котором есть вызов виртуального метода)
Timid
постоялец
 
Сообщения: 290
Зарегистрирован: 21.11.2007 21:33:15

Пред.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 22

Рейтинг@Mail.ru