Текущий архив: 2004.02.13;
Скачать: CL | DM;
Вниз
Перекрытие абстрактного метода Найти похожие ветки
← →
Альф © (2004-02-03 16:18) [0]Можно ли как-то определить - перекрыт ли абстрактный метод у наследника или нет, до вызова этого метода ???
Поясню на примере TStrings:
type
TMyStrings = class(TStrings)
public
procedure Clear(); override;
end;
procedure TMyStrings.Clear();
begin
ShowMessage("TMyStrings.Clear");
end;
procedure TForm1.Button1Click(Sender: TObject);
var
FStrings: TStrings;
begin
FStrings := TMyStrings.Create();
FStrings.Clear();
FStrings.Delete(0);
// ^^^ - вот тут получаем абстрактную ошибку, но так и должно быть
end;
Можно ли перед вызовом Delete(0) проверить - перекрыт ли метод - или нет ???
Существующий вариант решения с перехватом исключения меня не устраивает, т.е. такой
try
FStrings.Delete(0);
except
on EAbstractError // и далее
end;
Сложность в том что нужно убедиться в существовании перекрытого метода ДО вызова, примерно такое:
if ПерекрытЛиМетод(FStrings.Delete)
then FStrings.Delete(0);
← →
Vuk © (2004-02-03 16:20) [1]Может просто не делать метод абстрактным?
← →
Альф © (2004-02-03 16:27) [2]2Vuk © (03.02.04 16:20) [1]
Можно и не делать - просто пример был с TStrings.
Но всеже задача определения существования перекрытого метода остается :)
← →
KSergey © (2004-02-03 16:27) [3]А точно необходимо наследовать от TStrings? Вообще - что за класс и для чего предназначен? Вообще-то TStrings предполагает, что все его абстрактные методы перекроют.
А вообще на "королевстве" точно попадалать статейка про как определить. Где - не помню. Общая идея такова, что в таблице виртуюльных методов для абстрактного метода (а он всяко виртуальный) прописан нолик (nil по-дельфийски).
Видмо надо просто почитать какие-либо статейки про организацию виртуальных таблиц дельфийских. (вроде та статья посвящалась вызову метода "деда", а не "родителя"; во всяком случае работа с виртуальными таблицами там точно обсуждалась).
← →
KSergey © (2004-02-03 16:29) [4]В дополнение:
Вообще-то TStrings предполагает, что все его абстрактные методы перекроют, либо не будут вызывать абстрактные.
А иначе приведенный код весьма занятен: умышленно не переопределяем абстрактный метод, но вызываем его - может не надо его просто тогда вызывать? ;)
← →
Игорь Шевченко © (2004-02-03 16:32) [5]В журнале RSDN была статья на эту тему, номера не помню, но наверху есть ссылка.
← →
VMcL © (2004-02-03 17:00) [6]>>KSergey © (03.02.04 16:27) [3]
Не nil, а адрес проц. _AbstractError().
← →
KSergey © (2004-02-03 17:03) [7]> [6] VMcL © (03.02.04 17:00)
> >>KSergey © (03.02.04 16:27) [3]
>
> Не nil, а адрес проц. _AbstractError().
Да?
Впрочем, настаивать не буду. Мне запомнилось что-то про nil, вполне вероятно, что ошибаюсь (или автор статейки пидманул ;)
← →
VMcL © (2004-02-03 17:05) [8]>>KSergey © (03.02.04 17:03) [7]
Если бы был nil, то выскакивал бы AV, а не Abstract error.
← →
KSergey © (2004-02-03 17:09) [9]Ну почему, можно предположить, что штатный "прошаривальщик" виртуальных таблиц просто натыкаясь на nil вызывает обращение к _AbstractError() ;)
Впрочем, это лишь моя фантазия, как на самом деле - я не знаю.
Кинулся сейчас было в исходники - но это же думать надо... ;)
← →
Skier © (2004-02-03 17:33) [10]RSDN 02.2002 "Обработка абстрактных методов в Delphi"
← →
jack128 © (2004-02-03 17:37) [11]http://rsdn.ru/article/Delphi/delphiabs.xml
Но вообще мне не понятно зачем это нужно.
> Существующий вариант решения с перехватом исключения меня
> не устраивает, т.е. такой
>
> try
> FStrings.Delete(0);
> except
> on EAbstractError // и далее
> end;
Чем конкретно тя этот вариант не устраивает?
← →
Тимохов © (2004-02-03 17:40) [12]Не устараивает он его потому как нужно определить до вызова.
Вообще, нечего насиловать дельфи. ИМХО, конечно, но если возникают такие потребности, то что-то не так в архитектуре программы... Повторюсь, что это имхо.
← →
Vuk © (2004-02-03 17:46) [13]to Тимохов:
>если возникают такие потребности, то что-то не так в архитектуре
>программы...
Во-во. Ибо нефиг вообще классы с неперекрытыми абстрактными методами создавать.
← →
jack128 © (2004-02-03 17:58) [14]
> Не устараивает он его потому как нужно определить до вызова.
Это я понял. Я не понял ЗАЧЕМ ему нужно определить абстрактность метода до вызова этого метода.
← →
Mystic © (2004-02-03 17:59) [15]Имхо, ошибка проектирования. Такой задачи возникать не должно.
← →
WebErr © (2004-02-03 18:42) [16]BeginUpdate и EndUpdate обычно вызываются автоматически, но в твоём случае это надо делать ручками! Между ними порть хоть весь TString, они обеспечат правильное выделение памяти под процесс. (Я думал это все знают.) Обязательно используй try-finally. Исходник не дам - думать в-лом. :)
← →
Тимохов © (2004-02-03 19:29) [17]
> jack128 © (03.02.04 17:58) [14]
>
> > Не устараивает он его потому как нужно определить до вызова.
> Это я понял. Я не понял ЗАЧЕМ ему нужно определить абстрактность
> метода до вызова этого метода.
Думаю он сам не до конца сформулировал для себя, зачем ему это...
← →
Юрий Федоров © (2004-02-03 21:35) [18]Я бы не утверждал так категорично, что абстрактные методы должны быть перекрыты всегда, ситуаци бывают разные, главное - понимать, что делаешь
TAbstractClass = class
...
protected
procedure AbstractPtr(); virtual; abstract;
end;
PSinglePointerArray = ^TSinglePointerArray;
TSinglePointerArray = array[0..0] of Pointer;
...
var Vmt : PSinglePointerArray;
byte_offset: longword;
//Мы в методе этого класса
Vmt := pointer(ClassType);
//Метод абстрактный
asm
mov byte_offset, vmtoffset <тут ИмяКласса.ИмяМетода>
end;
if pointer(pointer(TAbstractClass)^) = Vmt^[byte_offset shr 2] then
Вроде что-то типа того :-)
← →
Альф © (2004-02-04 10:02) [19]Спасибо всем кто откликнулся.
Очень помогла эта статья на RSDN - Обработка абстрактных методов в Delphi
Страницы: 1 вся ветка
Текущий архив: 2004.02.13;
Скачать: CL | DM;
Память: 0.51 MB
Время: 0.04 c