我对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 AND通过IListModel接口。 或者我可以引入一个新的接口IMyModel并通过MyApp类中的此接口保存模型。我必须使用ShowModel方法中的Supports(...)来获取IListModel接口。 或者我从另一个非引用基类(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;
这个实现是否正常?
答案 0 :(得分:7)
如果要使用接口附带的引用计数,则只应通过接口引用该对象。除了通过接口之外没有对象的引用,也不会自己释放对象。
或者你可以通过重写_AddRef和_Release来禁用引用计数,并像你习惯的那样销毁对象。这就是TComponent所做的。
或者保持引用计数,但是当您像对象一样引用它时调用AddRef和Release。
修改强>
使用const参数可以防止引用计数更新并加快代码速度:
constructor Create(const model : IListModel); reintroduce;
答案 1 :(得分:1)
如果需要Interfaces和object引用,只需从TInterfacedPersistent(在Classes.pas中声明)而不是TInterfacedObject派生。请注意,您必须确保在释放实例时仍未保留任何接口引用。