2010-11-12 33 views
4

我對Delphi和Delphi中的接口沒有太多經驗。防止通過接口傳遞對象的破壞

實施例:

IListModel = interface 
    function At(row, col : Integer) : String; 
end; 

MyModel = class(TInterfacedObject, IListModel) 
public 
    function At(row, col : Integer) : String; 
    procedure ManipulateA; 
    procedure ManipulateBogus; 
end; 

沒有可以可視化實現IListModel接口的對象的視圖。

View = class(TForm) 
public 
    constructor Create(model : IListModel); reintroduce; 
end; 

我的應用程序擁有爲MyModel實例

MyApp = class({...}) 
strict private 
    model : MyModel; 
public 
// ... 
end; 

在應用程序中我創建了模型,並使用它。

procedure MyApp.LoadModel; 
procedure MyApp.OnFoo; 
begin 
    model.ManipulateBogus; 
end; 

現在,我想表明我不知道什麼是解決這個問題的最好辦法中的數據

procedure MyApp.ShowModel; 
var 
    v : View; 
begin 
    v := View.Create(model); // implicit to IListView > refCount=1 
    v.ShowModal; 
    FreeAndNil(v); 
    // refCount = 0 
    // oops, my model is dead now 
end; 

。 在MyApp中,我可以同時擁有實例模型:MyModel和通過IListModel接口。 或者我可以引入一個新的接口IMyModel,並通過MyApp類中的這個接口保存模型。我必須使用ShowModel方法中的Supports(...)來獲取IListModel接口。 或者我從另一個非refcounting基類(TInterfacedPersistent或自寫的類)派生MyModel類。任何其他想法?

在這種情況下使用接口的最佳方式是什麼?

編輯: 非裁判計數的基類:

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

function NonRefCountingObject._AddRef: Integer; 
begin 
    Result := -1; // no reference counting 
end; 

function NonRefCountingObject._Release: Integer; 
begin 
    Result := -1; // no reference counting 
end; 

這是實現好不好?

回答

7

如果要使用接口附帶的引用計數,則只應通過接口引用該對象。除了通過接口之外,不引用其他對象,也不要自己釋放對象。

或者您可以通過覆蓋_AddRef和_Release來禁用引用計數,並像您慣用的那樣銷燬對象。這是TComponent所做的。或者保持引用計數,但在引用AddRef和Release時像引用對象一樣調用AddRef和Release。

編輯

使用常量參數防止引用計數更新和加速你的代碼:

constructor Create(const model : IListModel); reintroduce; 
+0

Thx爲您的答案。用編輯中的NonRefCountingObject類替換TInterfacedObject或TComponent基類是否安全?這個實現是否正確? – hansmaad 2010-11-12 08:35:00

+0

是的,正確的 – 2010-11-12 11:05:42

+1

@hansmaad:Lars在他的第一句話中的含義是,你應該用'model:IListModel'替換'MyApp'中的'model:MyModel'。這確保'MyApp'保持一個引用(直到'MyApp'死亡;然後'model'的refcount減少,當refcount變爲零時,它被自動釋放)。 – 2010-11-12 12:07:45

1

如果同時需要,接口和對象引用,只是從TInterfacedPersistent獲得(在類中聲明.pas)而不是TInterfacedObject。請注意,在釋放實例時,您必須確保沒有接口引用仍然存在。

+0

在TInterfacedObject,TInterfacedPersistent和類似的對象/接口混合體的任何地方有沒有很好的介紹性書寫? – 2010-11-12 22:01:02