Форум: "Основная";
Текущий архив: 2003.06.02;
Скачать: [xml.tar.bz2];
ВнизКак определить, является ли вызываемый метод абстрактным? Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.008 c