为通用对象列表创建对象

时间:2010-08-06 08:02:05

标签: delphi oop generics

我不确定这是否可以在Delphi中使用。我环顾四周,似乎无法找到答案(示例或不当行为,这是不可能的):

我有一个通用列表类,我想创建一个泛型类型的实例。例如:

type
  TTypeA = class(TObject);

procedure Test;
var
  MyList: TobjectList<TTypeA>;
  NewListObject: TTypeA;
begin
  MyList := TObjectList<TTypeA>.Create;
  NewListObject := MyList.xxx //what to put on the xxx
end;

是否可以创建一个函数xxx来创建TTypeA类型的新对象?

@jeroen:谢谢你的回答。但是,我在问题中忘了一个重要的细节:

我希望这段代码也适用于任何其他类型,因此没有关于TObjectList的类型T的先验知识。我可能会创建以下列表:

MyList: TObjectList<TCar>;
MyList: TObjectList<TBike>;

在不知道MyList是否包含TCar或TBike(都来自相同的基类和相同的构造函数)的情况下,我想向MyList添加一个新项目。

根据Uwe Raabe的建议,我遇到了下一个问题:

我将课程修改为

TMyObjectList<T:class, constructor> = class(TMyBaseObjectList<T>)

其中TMyBaseObjectList定义为

TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList)

现在我收到一个错误: 类型参数“T”与类型“T:TMyBaseObject”

不兼容

5 个答案:

答案 0 :(得分:3)

如你所知,你为什么不写

NewListObject := TTypeA.Create;
MyList.Add(NewListObject);

这是在这里做的自然方式。 (我刚刚通过Jeroen的类似回答通知)

如果您希望容器创建对象,则必须创建一个后代类,该类可以更多地了解创建实例的泛型类型。构造函数约束可能对此有所帮助。

type
  TMyObjectList<T:class, constructor> = class(TObjectList<T>)
  public
    function NewObject: T;
  end;

function TMyObjectList<T>.NewObject: T;
begin
  result := T.Create;
end;

注意:这仅在实际类型具有名为 Create 的无参数构造函数时才有效。

更新:这将有助于

  TMyObjectList<T:constructor, TMyBaseObject> = class(TObjectList<T>)
  public
    function NewObj: T;
  end;

答案 1 :(得分:0)

xxx处,输入:TTypeA.Create(...); where ...是创建构造函数的参数。

答案 2 :(得分:0)

我的猜测是不可能的。除非您的列表中有项目,否则您可以这样做:

  NewListObject := MyList[0].ClassType.NewInstance as TTypeA;

答案 3 :(得分:0)

或者,您可以从TCollection下载列表类,从TCollectionItem下载您的项目,并将其用作基类。他们已经建成了所有的管道。要使用您的示例:

type
    TTypeA = class(TCollectionItem);

procedure Test;
var
    MyList: TCollection;
    NewListObject: TTypeA;

begin
    MyList := TCollection.Create(TTypeA);
    NewListObject := MyList.Add;
end;

编辑:我知道,它不是使用Generics,但您可以查看TCollection和TCollectionItem以获取更多设计思路,特别是在涉及所有权,通知和生命周期管理时。

答案 4 :(得分:0)

据我所知,你只能在泛型类的泛型类中使用无参数构造函数。

此问题的一个“解决方法”是使用匿名方法创建对象,但这意味着您需要创建许多方法。

至于另一个问题......

TMyObjectList<T:class, constructor> = class(TMyBaseObjectList<T>)
TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList)

我相信正确的宣言是

TMyObjectList<T:TMyBaseObject, constructor> = class(TMyBaseObjectList<T>)
TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList)

TMyBaseObjectList已经强制T为TMyBaseObject类型。如果在TMyObjectList中声明T:class,它将不满足TMyBaseObjectList的要求。