在 Delphi 中,所有纯虚函数的代码都指向了 System._AbstractError,我们可以通过它在基类中判定它是否子类是否实现了某个接口。不过遗憾的是,Delphi 中,_AbstractError 的地址,我们并不能直接用 @System._AbstractError 来获取地址,所以我们需要一点小技巧。
type
TAbstractHelper=class
protected
class var
FAbstractCode:Pointer;
procedure AbstractMethod;virtual;abstract;
public
class constructor Create;
class function IsAbstract<T>(AEvent:T):Boolean;static;
end;
{ TAbstractHelper }
class constructor TAbstractHelper.Create;
type
TMethodEvent=procedure of object;
var
AProc:TMethod;
AEvent:TMethodEvent absolute AProc;
begin
with TAbstractHelper.Create do
begin
AEvent:=AbstractMethod;
FAbstractCode:=aProc.Code;
Free;
end;
end;
class function TAbstractHelper.IsAbstract<T>(AEvent: T): Boolean;
var
AMethod:TMethod absolute AEvent;
begin
Result:=AMethod.Code=FAbstractCode;
end;
现在我们通过 TAbstractHelper.FAbstractCode 就取到了 System._AbstractError 的地址。
接下来就是如何实现判断:
TForm1=class(TForm)
...
protected
procedure InternalLoadData;virtual;abstract;
...
public
function SupportAutoload:Boolean;
end;
function TForm1.SupportAutoload: Boolean;
type
TInternalLoadDataEvent = procedure of object;
begin
Result:=TAbstractHelper.IsAbstract<TInternalLoadDataEvent>(InternalLoadData);
end;
上面的代码,TForm1 本身 InternalLoaData 是纯虚函数,SupportAutoload 会返回 false,而如果子类实现了 InternalLoadData 结果 SupportAutoload 就会返回 true,这样不用额外声明变量或子类重载函数,就可以实现完美的判定。
