Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.10.01;
Скачать: [xml.tar.bz2];

Вниз

Вызов метода предка класса минуя непосредственного предка.   Найти похожие ветки 

 
harisma   (2006-08-17 14:03) [0]

Вопрос такой: Есть 3 класса А - В - С. В унаследован от А, С унаследован от В. В классах есть перекрытый метод. Как мне из этого метода в классе С вызвать этот же метод класса А? типа как делается inherited для вызова метода непосредственного предка?


 
begin...end ©   (2006-08-17 14:07) [1]

Статический или виртуальный?


 
harisma   (2006-08-17 14:10) [2]

виртуальный


 
tesseract ©   (2006-08-17 14:13) [3]

A(ыуда).CallMethod -  должен вызваться именно метод класса А.


 
harisma   (2006-08-17 14:15) [4]

Спасибо. А еще варианты есть?


 
default ©   (2006-08-17 14:18) [5]

A = class
   procedure F; virtual;
 end;

 B = class(A)
   procedure F; override;
 end;

 C = class(B)
   procedure F; override;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure A.F;
begin
 ShowMessage("A.F");
end;

procedure B.F;
begin
 ShowMessage("B.F");
end;

procedure C.F;
var
 P: procedure of object;
begin
 TMethod(P).Code := @A.F;
 TMethod(P).Data := Self;
 P;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 O: C;
begin
 O := C.Create;
 O.F;
end;

как вариант


 
begin...end ©   (2006-08-17 14:21) [6]

Заменить ссылку на VMT, вызвать метод, восстановить ссылку.


 
default ©   (2006-08-17 14:22) [7]

tesseract ©   (17.08.06 14:13) [3]
так будет переполнение стека из-за бесконечной рекурсии


 
tesseract ©   (2006-08-17 14:22) [8]


> tesseract ©   (17.08.06 14:13) [3]


очепятался. там self.


 
Ketmar ©   (2006-08-17 14:24) [9]

> [4] harisma   (17.08.06 14:15)
а чем этот не нравится? есть конечно, и не один, ивсе через анус. но зачем?


 
default ©   (2006-08-17 14:25) [10]

Ketmar ©   (17.08.06 14:24) [9]
это неверный способ([4])


 
default ©   (2006-08-17 14:25) [11]

[3] то есть...


 
tesseract ©   (2006-08-17 14:26) [12]


> default ©   (17.08.06 14:22) [7]


Почему? Ведь должен вызваться метод родителя, а не потомка.


 
default ©   (2006-08-17 14:27) [13]

tesseract ©   (17.08.06 14:26) [12]
такой способ прокатит только для статических методов
с виртуальными такое не прокатит


 
begin...end ©   (2006-08-17 14:31) [14]

> Ketmar ©   (17.08.06 14:24) [9]

Смело...


 
Ketmar ©   (2006-08-17 14:34) [15]

> [13] default ©   (17.08.06 14:27)
пардон, не вчитался. снова извиняюсь.
что-то я сегодня слова теряю...


 
tesseract ©   (2006-08-17 14:36) [16]


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

 type Tclass1= class
  public
   procedure ShowMessage; virtual;
  end;

type Tclass2= class(Tclass1)
  public
   procedure ShowMessage; virtual;
  end;

type Tclass3= class(Tclass2)
  public
   procedure ShowMessage; virtual;
  end;
var
 Form1: TForm1;

implementation

{$R *.dfm}

{ Tclass1 }

procedure Tclass1.ShowMessage;
begin
MessageBox(0, "class 1", " no error", MB_ICONWARNING or MB_OK);
end;

procedure Tclass2.ShowMessage;
begin
MessageBox(0, "class 2", " no error", MB_ICONWARNING or MB_OK);
end;

procedure Tclass3.ShowMessage;
begin
Tclass1(self).ShowMessage;

end;
procedure TForm1.Button1Click(Sender: TObject);
var c1: Tclass1;
   c2: Tclass2;
   c3: Tclass3;
begin
c1:=tclass1.Create;
c2:=tclass2.Create;
c3:=tclass3.Create;

c3.ShowMessage;

c1.Free;
c2.Free;
c3.Free;
end;

end.


Вроде работает, но как там с полями/другими методами  будет не уверен.


 
tesseract ©   (2006-08-17 14:37) [17]


procedure Tclass3.ShowMessage;
begin
Tclass1(self).ShowMessage;
inherited ShowMessage;
MessageBox(0, "class 3", " no error", MB_ICONWARNING or MB_OK);
end;


так нагляднее, в  D7 работает.


 
begin...end ©   (2006-08-17 14:39) [18]

Пример к [6]:

var
 ObjC: C;
 TempClass: TClass;
begin
 ...
 TempClass := ObjC.ClassType;
 try
   PPointer(ObjC)^ := ObjC.ClassParent.ClassParent;
   ObjC.P;
 finally
   PPointer(ObjC)^ := TempClass;
 end;
 ...
end


 
default ©   (2006-08-17 14:42) [19]

tesseract ©   (17.08.06 14:37) [17]
блин, траблы у тебя с объектной моделью...
ты везде virtual пишешь - это значит новый метод, а не перекрытие старого...
тогда, конечно, приведение будет работать...


 
harisma   (2006-08-17 14:44) [20]

У меня этот метод объявлен как virtual только в классе А. В классах В и С он обїявляется как override.


 
begin...end ©   (2006-08-17 14:44) [21]

В [18] P -- это имя метода, конечно.


 
tesseract ©   (2006-08-17 14:44) [22]


> default ©   (17.08.06 14:42) [19]


насчёт этого  я как раз в курсе,  а что это не решение [0] ?


 
default ©   (2006-08-17 14:47) [23]

harisma   (17.08.06 14:44) [20]
дали уже два решения [5] и [18]
tesseract ©   (17.08.06 14:44) [22]
[20]


 
default ©   (2006-08-17 14:56) [24]

во всех(думаю нет ислючений) ООП языках, есть специальный синтаксис только для вызова метода предка
стоит задумать о архитектуре классов, прежде чем городить огород из подобных "финтов" - максимум простоты и логичности!


 
default ©   (2006-08-17 14:57) [25]

непосредственного предка


 
default ©   (2006-08-17 15:03) [26]

важно понять, что эти "финты" всего лишь заплаты для огрех проектирования
(скорее всего)
свою "крутость" в них показывать на самом деле не круто


 
WondeRu ©   (2006-08-17 15:08) [27]

вот в своем проекте нашел:
иерархия такая
A-B-C

type
 TDrawProj = procedure (Sender: TObject; const SelectRender: Boolean = False);

.....
procedure C.Draw(const SelectRender: Boolean = False);
begin
 TDrawProj(@A.Draw)(Self, SelectRender);
....
end;


 
tesseract ©   (2006-08-18 10:45) [28]


> default ©   (17.08.06 15:03) [26]


Я никогда свою крутость не показывал. Имхо как раз перезаписывание VMT - ошибка проектирования. Чистое ИМХО.


 
default ©   (2006-08-18 11:22) [29]

tesseract ©   (18.08.06 10:45) [28]
я ни в коем случае ни на кого не намекал говоря про крутость!
просто указал, что стоит задуматься автору сабжа над архитектурой класса прежде чем использовать выданные решения
подобные решения скорее как задачка для какого-нибудь собеседования, чем на реальное применение


 
default ©   (2006-08-18 11:24) [30]

WondeRu ©   (17.08.06 15:08) [27]
так делать в общем случае нельзя
вызывать надо процедуру объекта, а не обычную
в данном случае просто повезло, что работает



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2006.10.01;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.015 c
15-1158000666
AntiUser
2006-09-11 22:51
2006.10.01
Сортировка и ORDER BY


2-1157697536
Grid
2006-09-08 10:38
2006.10.01
Dbgrid


15-1157989615
Cyrax
2006-09-11 19:46
2006.10.01
Тонкости языка C++


2-1158207408
O.O
2006-09-14 08:16
2006.10.01
Погасить message


3-1154405567
AVK
2006-08-01 08:12
2006.10.01
Oracle. Проблема c вызовом функций. DAO





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский