我使用的是一个非常大的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类中实现?
答案 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.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;
答案 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ë的答案所示。