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

Sal*_*dor 10 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;
Run Code Online (Sandbox Code Playgroud)

我如何确定在运行时的Descendant类中是否实现了抽象方法?

RRU*_*RUZ 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;
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)


Rem*_*eau 5

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

\n


Zoë*_*son 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;
Run Code Online (Sandbox Code Playgroud)