2011-11-29 39 views
10

我正在使用一個非常大的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類中實現?

回答

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; 

,或者你可以比較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; 
4

查看VCL源代碼中TStream.Seek()方法的實現。它會執行類似的類似於後代的重寫檢查,而不涉及TRttiContext查找,只需通過其父/子vtable條目的簡單循環即可。

4
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; 
+0

謝謝,但如果使用這種方式,我需要爲每個類類型實現一個函數,而我最好是一個更一般的解決方案。 – Salvador

+0

我不確定你的代碼是否正確。 'ImplementsAbstractMethod(TChild2.Create)'將返回true,但'TChild2'和'TDescendantBase'都不會覆蓋'TMyBaseClass'的抽象'MyAbstractMethod'。 http://pastebin.com/JufNPJkg –

+0

@rinntech:謝謝你的提高。我用正確的代碼更新了答案。 –