Перемещайте объекты между контейнерами и теряйте интерфейс - PullRequest
0 голосов
/ 29 января 2012

Допустим, у нас есть интерфейс I, объект O и контейнер sl:

type
  rootInterface = Interface
  end;

  childOfRootInterface = interface(rootInterface)
  end;

  ObjectImplementsRootInterface = class(TObject, I)
  end;

  ObjectImplementsChildOfRootInterface = class(TOtherObject, I2);
  end;

var
  aStringList: TStringList;

Предполагается, что sl инициализирован.

Если мы сделаем

aStringList.Items.AddObject('root', ObjectImplementsRootInterface );

тогда мы не можем сделать

ObjectImplementsRootInterface  := I(aStringList.Items.Objects([0]));

потому что Дельфи это запрещает. так стараюсь:

ObjectImplementsRootInterface  := TObject(aStringList.Items.Objects([0]));

Однако мы вставили childOfRootInterface и хотим вернуть childOfRootInterface, поэтому мы делаем

ObjectImplementsChildOfRootInterface  := childOfRootInterface (sl.Items.Objects([0]));

Но ObjectImplementsChildOfRootInterface и ObjectImplementsRootInterface имеют разные суперсимволы!

Хотя они поддерживают один и тот же интерфейс, мы ничего не можем сделать.

В Java вы можете передавать объекты, если они поддерживают интерфейс. В Java это будет возможно, так что теперь после всего этого планирования; что я могу сделать в Delphi?

Обновление: поменял имена, однако пример мог бы одолеть меня и победить, не могу найти направо и налево.

Ответы [ 2 ]

1 голос
/ 29 января 2012

Вот пример рабочего кода:

program Project9054004;

{$APPTYPE CONSOLE}

uses
  Classes, SysUtils, Dialogs;

type  
  I = interface
  ['{6D39CF0A-839A-4DA3-B058-52E424702652}']
  end;

  O = class(TInterfacedObject, I)
  end;

var
  SL: TStrings;
  TempO: O;
  TempI: I;
begin
  ReportMemoryLeaksOnShutdown := True;

  SL := TStringlist.Create;
  try
    TempO := O.Create;
    SL.AddObject('a', TempO);

    if Supports(SL.Objects[0], I, TempI) then
    begin
      // use I
      TempI._AddRef;
      TempI._Release;
    end;

    ShowMessage(SL.Objects[0].ClassName);

  finally
    SL.Free;
  end;
end.

Чтобы избежать приведения типа hard, я использую GUID для интерфейса.

Поддержки могут использоваться для безопасного тестирования и присвоения объекта переменной типа I. Обратите внимание, что имена типов немного запутаны в вашем примере.

Жесткая типизация для интерфейсаневозможно для элементов в списке объектов.

0 голосов
/ 30 января 2012

Просто сдался и добавил еще одну структуру данных, которая может содержать этот XML и, как мы надеемся, сохранить инвариант, чтобы их нельзя было восстанавливать.

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