如何确定抽象方法是否已被实现?

10
我正在使用一个没有源代码的非常大的 Delphi 第三方库,该库有几个抽象方法的类。我需要在运行时确定后代类是否实现了抽象方法,以避免 EAbstractError:Abstract Error 并向用户显示自定义消息或使用另一个类。例如,在此代码中,我想在运行时检查是否已实现MyAbstractMethod
type
  TMyBaseClass = class
  public
    procedure MyAbstractMethod; virtual; abstract;
  end;

  TDescendantBase = class(TMyBaseClass)
  public
  end;

  TChild = class(TDescendantBase)
  public
    procedure MyAbstractMethod; override;
  end;

  TChild2 = class(TDescendantBase)
  end;

如何在运行时确定一个抽象方法是否在派生类中实现?

3个回答

11
你可以使用 Rtti,GetDeclaredMethods 函数获取反射类型中声明的所有方法列表。因此,您可以检查此函数返回的列表中是否存在该方法。
function MethodIsImplemented(const AClass:TClass;MethodName : string): Boolean;
var
  m   : TRttiMethod;
begin
  Result := False;
  for m in TRttiContext.Create.GetType(AClass.ClassInfo).GetDeclaredMethods do
  begin
   Result := CompareText(m.Name, MethodName)=0;
   if Result then
    break;
  end;
end;

或者您可以比较Parent.Name属性的TRttiMethod,并检查是否与当前类名匹配。

function MethodIsImplemented(const AClass:TClass;MethodName : string): Boolean;
var
  m   : TRttiMethod;
begin
  Result := False;
  m:=TRttiContext.Create.GetType(AClass.ClassInfo).GetMethod(MethodName);
  if m<>nil then
   Result:=CompareText(AClass.ClassName,m.Parent.Name)=0; 
end;

5
function ImplementsAbstractMethod(AObj: TMyBaseClass): Boolean;
type
  TAbstractMethod = procedure of object;
var
  BaseClass: TClass;
  BaseImpl, Impl: TAbstractMethod;
begin
  BaseClass := TMyBaseClass;
  BaseImpl := TMyBaseClass(@BaseClass).MyAbstractMethod;
  Impl := AObj.MyAbstractMethod;
  Result := TMethod(Impl).Code <> TMethod(BaseImpl).Code;
end;

谢谢,但如果使用这种方式,我需要为每个类类型实现一个函数,而我更喜欢一个更通用的解决方案。 - Salvador
我不确定你的代码是否正确。ImplementsAbstractMethod(TChild2.Create)将返回true,但是TChild2TDescendantBase都没有覆盖TMyBaseClass的抽象方法MyAbstractMethod。http://pastebin.com/JufNPJkg - Daniel Marschall
@rinntech:谢谢提醒。我已经更新了答案,加入了正确的代码。 - Zoë Peterson

4

看一下VCL源代码中32位版本的TStream.Seek()方法的实现(在Classes.pas中)。它执行一个检查,以确保已经覆盖了64位版本的Seek()方法,然后才调用它。这并不涉及使用TRttiContext进行查找,只是通过其父/子VTable条目简单地循环,类似于Zoë的答案所显示的方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接