2013-02-18 56 views
9

我需要一個實現沒有引用計數接口的類。我做了以下操作:將對象轉換爲沒有TInterfacedObject作爲基類的接口類型

IMyInterface = interface(IInterface) 
     ['{B84904DF-9E8A-46E0-98E4-498BF03C2819}'] 
     procedure InterfaceMethod; 
    end; 

    TMyClass = class(TObject, IMyInterface) 
    protected 
     function _AddRef: Integer;stdcall; 
     function _Release: Integer;stdcall; 
     function QueryInterface(const IID: TGUID; out Obj): HResult;stdcall; 
    public 
     procedure InterfaceMethod; 
    end; 

    procedure TMyClass.InterfaceMethod; 
    begin 
     ShowMessage('The Method'); 
    end; 

    function TMyClass.QueryInterface(const IID: TGUID; out Obj): HResult; 
    begin 
     if GetInterface(IID, Obj) then 
      Result := 0 
     else 
      Result := E_NOINTERFACE; 
    end; 

    function TMyClass._AddRef: Integer; 
    begin 
     Result := -1; 
    end; 

    function TMyClass._Release: Integer; 
    begin 
     Result := -1; 
    end; 

沒有引用計數工作正常。但我擔心的是,我不能用as運營商投TMyClassIMyInterface

var 
    MyI: IMyInterface; 
begin 
    MyI := TMyClass.Create as IMyInterface; 

我給

[DCC錯誤] E2015操作並不適用於這一運算對象類型

的問題消失TMyClassTInterfacedObject派生 - 即我可以做這樣的投射沒有編譯器錯誤。顯然,我不想使用TInterfacedObject作爲基類,因爲它會使我的類引用被計算在內。爲什麼這樣的鑄造不允許,以及如何解決這個問題?

+0

通過將GUID添加到接口聲明中,您可能會獲得更好的結果。在'= interface'行後面添加一個新行,然後按下Ctrl-Shft-G。 'as','GetInterface'和'supports'等需要能夠通過GUID識別接口才能工作。 – 2013-02-18 08:21:31

+0

您沒有仔細閱讀我的文章。當我從TInterfacedObject派生它的作品。 GUID在這裏沒有任何關係。您只需要使用GUID來使用COM。 – 2013-02-18 08:23:36

+0

嗯,哪個Delphi版本? – 2013-02-18 08:24:58

回答

14

您的代碼中不能使用as的原因是您的班級在其支持的接口列表中沒有明確列出IInterface。即使您的界面來自IInterface,除非您實際列出了該界面,但您的類不支持它。

所以,瑣碎的解決方法是聲明你的類是這樣的:

TMyClass = class(TObject, IInterface, IMyInterface) 

,你的類需要實現IInterface的原因是什麼編譯器,以實現as投依託。

我想說的另一點是,你應該避免使用接口繼承。總的來說,它沒有什麼用處。使用接口的好處之一是,您可以從實現繼承中獲得單一繼承約束。

但是在任何情況下,所有的德爾福接口automatically inherit from IInterface所以在你的情況下沒有一點指定。我會聲明你的接口是這樣的:

IMyInterface = interface 
    ['{B84904DF-9E8A-46E0-98E4-498BF03C2819}'] 
    procedure InterfaceMethod; 
end; 

更廣泛地說,你應該儘量不要在你的接口中使用繼承。通過採取這種方法,你會鼓勵更少的耦合,並且導致更大的靈活性。

+0

接口繼承是**不是**實現繼承。 Delphi中的任何接口都來自'IInterface'。最後一句話不清楚。 – kludg 2013-02-18 09:07:47

+0

@Serg那個接口繼承是**不是**實現繼承正是我試圖做的一點。我會嘗試清除它。 – 2013-02-18 09:12:50

+1

感謝您的解釋。現在我發現它很明顯,也很明顯:) – 2013-02-18 09:39:32