Как убедиться, что будущее наследование отменяет процедуру? - PullRequest
3 голосов
/ 26 февраля 2012

Я пишу класс с некоторыми виртуальными / абстрактными процедурами, которые я ожидаю переопределить.Однако они также не могут быть переопределены, что тоже хорошо.Проблема заключается в том, чтобы выяснить, была ли одна из этих процедур переопределена или нет.Если они не отменяются, я не должен пытаться вызывать эти процедуры, и вместо этого мне нужно заняться чем-то другим.Если я пытаюсь вызвать один из них и не переопределить его, я получаю Abstract Error.

Есть ли способ определить, были ли переопределены эти процедуры или нет?

Вот примеро том, как они объявлены:

type
  TMyClass = class(TObject)
  protected
    procedure VProc; virtual;
    procedure VAProc; virtual; abstract;
  end;

Ответы [ 5 ]

4 голосов
/ 27 февраля 2012

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

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

В вашем случае просто объявите их как virtual и предоставьте им реализацию по умолчанию NO-OP (Без операции), которую требует ваш дизайн:

type
  TMyBaseClass = class
    protected
      procedure SomeProc; virtual;
  end;


procedure TMyBaseClass.SomeProc;
begin
  // NO-OP
end;

Примечание - это иллюстрирует мое личное соглашение о документировании преднамеренного НО-ОП, а не о том, чтобы просто оставить пустую реализацию.

Любые шеннаниганы, через которые вы проходите, пытаясь определить, был ли объявленный абстрактный метод переопределен или нет, и вызвать его - или нет - на основе этого теста, скорее всего, будут стоить больше времени, чем простой вызов реализации NO-OP. , Кроме того, если вам когда-либо понадобится внедрить реализацию в этом базовом классе, вам не нужно менять метод с абстрактного на неабстрактный (возможно, нарушая те схемы «обнаружения», которые были у вас в этом методе, и, конечно же, переводя их стоимость в ничто. но чисто накладные расходы).

4 голосов
/ 26 февраля 2012

Вы можете сделать что-то вроде этого.Обратите внимание, что я удалил «абстрактный».Это может работать с «абстрактным», но я не пробовал.

type 
  TMyClass = class(TObject) 
  protected 
    procedure VProc; virtual; 
    procedure VAProc; virtual; //abstract;
  end; 


function GetVAProcAddress(Instance: TMyClass): pointer;
var
  p: procedure of object;
begin
  p := Instance.VAProc;
  result := TMethod(p).Code;
end;


//in one of the TMyClass methods you can now write:

  if GetVAProcAddress(self) <> @TMyClass.VAProc then
4 голосов
/ 26 февраля 2012

Я думаю, что это неправильный подход, он действительно пахнет очень плохо .. Некоторые предложения:

  • Используйте неабстрактные методы, которые делают то, что вы хотите делать, когда они не переопределены.
  • Используйте события вместо методов.Легко проверить, были ли они назначены.
1 голос
/ 26 февраля 2012

Если вы получили строчный код, подобный этому:

lObj := TMyClass.Create;

, вы заметите, что компилятор выведет предупреждение о том, что вы создаете экземпляр TMyClass, содержащий абстрактный метод TMyClass.VAProc.

1 голос
/ 26 февраля 2012

Используйте RTTI, чтобы получить адрес метода рассматриваемого виртуального метода для класса в вопросах. Сравните его с адресом метода для того же метода базового класса. Если это не то же самое, то метод был переопределен.

...