Предотвратить уничтожение объекта, переданного интерфейсом - PullRequest
4 голосов
/ 12 ноября 2010

У меня совсем нет опыта работы с интерфейсами в 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.Мне пришлось использовать, если Supports (...) в методе ShowModel, чтобы получить интерфейс IListModel.Или я извлекаю класс MyModel из другого базового класса без пересчета (TInterfacedPersistent или самописный класс).Любые другие идеи?

Каков наилучший способ работы с интерфейсами в таких ситуациях?

Редактировать: Базовый класс без учета подсчета:

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;

Является ли эта реализацияок?

Ответы [ 2 ]

7 голосов
/ 12 ноября 2010

Если вы хотите использовать подсчет ссылок, который поставляется с интерфейсами, вы должны ссылаться на этот объект только через интерфейсы. Нет ссылок на объект, кроме как через интерфейсы и не освобождайте объект самостоятельно.

Или вы можете отключить подсчет ссылок, переопределив _AddRef и _Release и уничтожив объект, к которому вы привыкли. Это то, что делает TComponent.

Или продолжайте подсчет ссылок, но вызывайте AddRef и Release, когда вы ссылаетесь на него как на объект.

редактировать

использование параметра const предотвращает обновление счетчика ссылок и ускоряет ваш код:

constructor Create(const model : IListModel); reintroduce;
1 голос
/ 13 ноября 2010

Если вам нужны и интерфейсы, и ссылки на объекты, просто наследуйте TInterfacedPersistent (объявленный в Classes.pas) вместо TInterfacedObject.Помните, что при освобождении экземпляра вы должны убедиться, что ссылка на интерфейс по-прежнему не удерживается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...