如何将 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;
我对 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;