我如何确定是否实现了抽象方法?

时间:2011-11-29 02:13:00

标签: delphi delphi-xe

我使用的是一个非常大的delphi第三方库,没有源代码,这个库有几个带抽象方法的类。我需要确定运行时Descendant类是否实现了abtract方法以避免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;

如何判断抽象方法是否在运行时的Descendant类中实现?

3 个答案:

答案 0 :(得分:10)

您可以使用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.NameTRttiMethod属性,并检查是否与当前的班级名称匹配。

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;

答案 1 :(得分: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;

答案 2 :(得分:4)

查看VCL源代码中的TStream.Seek()方法的32位版本的实现(在Classes.pas中)。它会执行检查以确保在调用之前已覆盖64位版本的Seek()。它不涉及TRttiContext查找,只是通过其父/子VTable条目的简单循环,类似于Zoë的答案所示。