Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.06.02;
Скачать: CL | DM;

Вниз

Как определить, является ли вызываемый метод абстрактным?   Найти похожие ветки 

 
Aleksandr ©   (2003-05-20 15:28) [0]

У базового объекта есть ряд абстрактных методов, по необходимости перекрываемых в потомках. Но некоторые потомки не используют эти методы, хотя они вызываются внутри используемых, и, соответственно, не переопределяют их, что при вызове приводит к Abstract Error. Есть ли более "культурный", чем try...except, способ узнать, что метод остался абстрактным?


 
AlexGreG ©   (2003-05-20 15:30) [1]

if Assigned(AbstractMethod) then AbstractMethod

или

if not AbstractMethod=nil then AbstractMethod

пробуй



 
Юрий Зотов ©   (2003-05-20 15:43) [2]

> Есть ли более "культурный", чем try...except, способ узнать,
> что метод остался абстрактным?

Есть - обращать внимание на предупреждения компилятора. И делать так, чтобы их никогда не было.


 
Aleksandr ©   (2003-05-20 15:50) [3]

Спасибо.


 
Skier ©   (2003-05-20 15:53) [4]

>Aleksandr © (20.05.03 15:28)
Можно сделать так :
(правда нужно будет код класса-предка править.)
Но как вариант...

TBasicClass = class(...)
protected
procedure SomeProc; virtual;
end; //TBasicClass

//..................

procedure TBasicClass.SomeProc;
begin
//do nothing...
end; //TBasicClass




 
Aleksandr ©   (2003-05-20 16:06) [5]

2 Юрий Зотов:

А теперь расскажите мне, как выглядит сообщение компилятора о том, что абстрактный метод не перекрыт? У меня отключено только одно сообщение - о депрекатных символах, но компилятор мне более ничего не пишет. Кроме того, если Вы невнимательно прочли мой вопрос, мне не надо найти неперекрытые методы, я их итак знаю, мне нужно корректно обработать их вызовы. Классический пример использования абстрактностей:

TBaseClass = class
protected
...
function DoEditRecord : boolean; virtual; abstract;
public
...
procedure EditRecord;
end;

procedure TBaseClass.EditRecord;
begin
GetPos;
if DoEditRecord then begin
RefreshData;
GoToPos
end
end;

А теперь представьте ситуацию, когда метод вызывается по двойному клику на гриде, но далеко не каждая грида предусматривает редактирование, тогда как базовый класс позволяет это делать.


 
Skier ©   (2003-05-20 16:18) [6]

>Aleksandr © (20.05.03 16:06)

> но далеко не каждая грида предусматривает редактирование,

"грида" (потомок), которая не предусматривает редактирование
должна реализовать метод DoEditRecord - сделать его пустым, например...


 
Anatoly Podgoretsky ©   (2003-05-20 16:22) [7]

Тут или обработает ошибку система, на первом по уровню обработчике except или если ты хочешь обрабатывать ошибки сам в этом месте то будь добр сделать защищенный блок, а то что ты хочешь сам, так на это намекает if DoEditRecord


 
Юрий Зотов ©   (2003-05-20 16:46) [8]

> Aleksandr © (20.05.03 16:06)

> А теперь расскажите мне, как выглядит сообщение компилятора о
> том, что абстрактный метод не перекрыт?

ОК, рассказываю. Оно выглядит вот так:
[Warning] Unit1.pas(27): Constructing instance of "TStrings" containing abstract methods


> У меня отключено только одно сообщение - о депрекатных
> символах, но компилятор мне более ничего не пишет.

У меня D5, и в опциях проекта есть только "Show Hints" и "Show Warnings". Поэтому - о каких депрекатных символах Вы говорите, я не знаю, но знаю, что чудес не бывает. Проверяйте настройки, что ж тут еще скажешь.


> Классический пример использования абстрактностей

Излишне. Полагаю, с сабжем я знаком далеко не понаслышке.


> Кроме того, если Вы невнимательно прочли мой вопрос, мне не
> надо найти неперекрытые методы, я их итак знаю, мне нужно
> корректно обработать их вызовы.

Ваш вопрос я прочел внимательно. А вот Вы, боюсь, невнимательно прочитали ответ. Там была еще одна фраза - "делать так, чтобы их никогда не было". Если неперекрытый абстрактный метод реально вызывается - естественно, будет ошибка. Поэтому его надо перекрывать хотя бы пустым методом (stub). Обычная практика. Таких "пустых" методов и в самой VCL хватает.




 
default ©   (2003-05-20 22:30) [9]

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;

TMyClass = class
procedure Proc; virtual; abstract;
procedure Proc2; virtual; abstract;
end;

var
Form1: TForm1;
Obj: TMyClass;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
Addr: Cardinal;
begin

Obj := TMyClass.Create;
asm
push eax
push edx
mov eax,Obj
mov edx,[eax]
mov eax,[edx + VMTOffset TMyClass.Proc2]
mov Addr,eax
pop edx
pop eax
end;
if Addr = $402918 then Caption := "TMyClass.Proc2 - абстрактный метод"

end;

end.

вот так можно в Delphi 6
в других версиях - не уверен


















 
vuk ©   (2003-05-20 22:53) [10]

Вообще говоря, если в каком-то случае требуется определить абстрактный метод или нет, то налицо ошибка проектирования связанная с неправильным пониманием назначения абстрактных методов. Абстрактные методы предназначены для того, чтобы быть обязательно перекрытыми в потомках, а не для того, чтобы быть заглушкой. Так что самый правильный метод решения здесь: Skier © (20.05.03 15:53)


 
Юрий Зотов ©   (2003-05-20 22:54) [11]

Можно, конечно, и через VMT. Только вот на эту строку:
Obj := TMyClass.Create;
компилятор все равно обругается.


 
Anatoly Podgoretsky ©   (2003-05-21 07:55) [12]

vuk © (20.05.03 22:53)
Асболютно согласен, из за этого получаются непрятные ошибки, хотя бы просто inherited, потом иначе будут непрятности.


 
default ©   (2003-05-21 21:40) [13]

Юрий Зотов © (20.05.03 22:54)
всмысле? ругается-то пусть, главно что работает?!
vuk © (20.05.03 22:53)
да это-то всем понятно
просто вопрос был - как определить абстрактный метод был


 
vuk ©   (2003-05-21 22:01) [14]

to default:
>просто вопрос был - как определить абстрактный метод был
По-хорошему - ничего не трогать. Пусть ругается, чем громче, тем лучше, т.к. применение таких классов - ошибка. К тому же, как я понимаю, есть какая-то библиотека классов собственного написания, где возникла проблема. Так может её лучше немного подкорректировать и избавиться от проблемы навсегда? Тем более, что решение-то простейшее.


 
default ©   (2003-05-21 23:40) [15]

vuk © (21.05.03 22:01)
бесспорно
я предложил просто как вариант


 
Юрий Зотов ©   (2003-05-21 23:53) [16]

> default © (21.05.03 21:40)

Немного не так. Вопрос был о КУЛЬТУРНОМ способе определения абстрактного метода. Так вот, САМЫЙ культурный способ - это обращать внимание на сообщения компилятора и писать код так, чтобы их не было. Ни одного. Без этого о какой-либо культуре программирования говорить просто не стоит.

А насчет "главно что работает" - это ОЧЕНЬ ошибочное мнение. Главное - чтоб не просто работало, а чтоб работало:
а). надежно;
б). не только сегодня, но и завтра, после каких-то изменений;
в). и чтоб позволяло легко эти изменения вносить.

Так вот, если компилятор выдает хотя бы один варнинг, то все эти три пункта становятся негарантированными. И когда завтра потребуется что-то изменить, то как после этого поведет себя такая программа - одному Аллаху известно. И какие потребуются усилия для ее возврата в норму - тоже известно ему одному.



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

Текущий архив: 2003.06.02;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.02 c
9-2735
VikKo
2002-12-17 22:54
2003.06.02
Дым, взрывы и fps


14-3076
Lopuhh
2003-05-16 12:55
2003.06.02
О БК


1-3001
kull
2003-05-20 11:39
2003.06.02
Если путь не влезает?


1-2878
User
2003-05-22 12:43
2003.06.02
Быстрое копирование блоков памяти


14-3081
Дмитрий К.К.
2003-05-16 05:23
2003.06.02
Именинники 16 мая