防止破坏界面传递的对象

han*_*aad 4 delphi interface

我对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;
Run Code Online (Sandbox Code Playgroud)

有一个视图可以显示实现IListModel接口的对象.

View = class(TForm)
public
    constructor Create(model : IListModel); reintroduce;
end;
Run Code Online (Sandbox Code Playgroud)

我的应用程序拥有MyModel实例

MyApp = class({...})
strict private
    model : MyModel;
public
 // ...
end;
Run Code Online (Sandbox Code Playgroud)

在应用程序中,我创建模型并使用它.

procedure MyApp.LoadModel;
procedure MyApp.OnFoo;
begin
    model.ManipulateBogus;
end;
Run Code Online (Sandbox Code Playgroud)

现在,我想显示数据

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;
Run Code Online (Sandbox Code Playgroud)

我想知道什么是解决这个问题的最佳方法.在MyApp中我可以同时拥有两个实例模型:MyModel AND通过IListModel接口.或者我可以引入一个新的接口IMyModel并通过MyApp类中的此接口保存模型.我必须使用ShowModel方法中的Supports(...)来获取IListModel接口.或者我从另一个非引用基类(TInterfacedPersistent或自写类)派生MyModel类.还有其他想法吗?

在这种情况下使用接口的最佳方法是什么?

编辑:非ref计数基类:

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;
Run Code Online (Sandbox Code Playgroud)

这个实现好吗?

Lar*_*ens 7

如果要使用接口附带的引用计数,则只应通过接口引用该对象.除了通过接口之外没有对象的引用,也不会自己释放对象.

或者你可以通过重写_AddRef和_Release来禁用引用计数,并像你习惯的那样销毁对象.这就是TComponent所做的.

或者保持引用计数,但是当您像对象一样引用它时调用AddRef和Release.

编辑

使用const参数可以防止引用计数更新并加快代码速度:

constructor Create(const model : IListModel); reintroduce;
Run Code Online (Sandbox Code Playgroud)

  • 如果您的界面不支持您尝试执行的操作,那么您要么尝试做一些您不应该做的事情,要么您的界面是错误的. (2认同)