如何将 TObjectList 用于任意 class 类型?

How to use TObjectList for arbitrary class type?

我对 Delphi 中的泛型仍然有点模糊,但是 TObjectList<> 已经相当广泛地使用了。现在我有一个情况,我有一个带有这样一个私有字段的基础class,但需要为任意class创建,也从另一个基础继承。

澄清一下,我有两个基数 classes:

type
  TItem = class;
  TItems = class;

  TItemClass = class of TItem;

  TItem = class(TPersistent)
  private
    FSomeStuffForAllIneritedClasses: TSomeStuff;
  end;

  TItems = class(TPersistent)
  private
    FItems: TObjectList<TItem>;
    FItemClass: TItemClass;
  public
    constructor Create(AItemClass: TItemClass);
    destructor Destroy; override;
    function Add: TItem;
    ...
  end;

这对classes然后进一步继承为更具体的classes。我希望为所有对象共享对象列表,而每个对象在内部实际上拥有不同的类型。

type
  TSomeItem = class(TItem)
  private
    FSomeOtherStuff: TSomeOtherStuff;
    ...
  end;

  TSomeItems = class(TItems)
  public
    function Add: TSomeItem; //Calls inherited, similar to a TCollection
    procedure DoSomethingOnlyThisClassShouldDo;
    ...
  end;

现在的问题是创建实际的对象列表。我正在尝试这样做:

constructor TItems.Create(AItemClass: TItemClass);
begin
  inherited Create;
  FItemClass:= AItemClass;
  FItems:= TObjectList<AItemClass>.Create(True);
end;

但是,代码洞察对此有抱怨:

Undeclared Identifier AItemClass

更重要的是,编译器还有一个不同的抱怨:

Undeclared Identifier TObjectList

其中,我确实在本单元中使用了 System.Generics.Collections

我在这里做错了什么,我应该怎么做?

TObjectList 不应该以这种方式使用。它最初定义为 TObjectList<TItem> 的事实意味着它希望您也以这种方式创建它。它需要用您打算创建它的精确 class 来定义。

相反,只需使用 TItem 创建它,然后每当您创建一个应该添加到此列表的新项目时,然后 您使用class 类型。任何时候您需要访问此列表中的项目,只需即时投射即可。

例如...

Result:= FItemClass.Create;
FItems.Add(Result);

...可以是您的 Add 函数的内容。

使 TItems 通用:

TItems<T: TItem, constructor> = class(TPersistent)
private
  FItems: TObjectList<T>;
public
  constructor Create;
  destructor Destroy; override;
  function Add: T;
  ...
end;

constructor TItems.Create;
begin
  inherited Create;
  FItems:= TObjectList<T>.Create(True);
end;

function TItems<T>.Add: T;
begin
  Result := T.Create;
  FItems.Add(Result);
end;

如果继承,只需输入正确的泛型参数:

TSomeItems = class(TItems<TSomeItem>)
public
  procedure DoSomethingOnlyThisClassShouldDo;
  ...
end;