我在泛型和构造函数方面遇到了一些麻烦。
我想有一个泛型类,可以处理(和创建)同一个类的多个对象。此外,我有一些代码,我想使用任何具体的类实际上是。
我认为泛型是一个很好的解决方案,但我不太确定。
type
TMultiBlock<T: IBlock, constructor> = class(TObject)
blocks: array of array of T;
constructor Create(const owner: someClass, const n: integer);
end;
constructor TMultiBlock<T>.Create(const owner: someClass, const n: integer);
var
i: integer;
begin
for i := 0 to n-1 do
T.Create();
end;
上面的解决方案是可行的,但是被调用的Create()
不是我给予泛型的T
类。
我知道我可以在TMultiBlock
类之外做Create
,因为我知道T
类在那里,如下所示:
TM := TMultiBlock<TFinestra>.Create();
for i := 0 to n do
begin
TM.blocks[i] := TFinestra.Create();
end;
这里的类TFinestre
是我想在泛型中使用的类之一,但问题是我想对T
元素做一些通用操作,这些操作对任何T
类型都是通用的,所以我想对TMultiBlock
做。IBlock
是由T
类型的每个类实现的接口。
1条答案
按热度按时间i86rm4rw1#
用OOP的术语来说,接口是一个纯粹的抽象定义。它可以由许多不同的类来实现。你不能从接口创建对象(除非接口给你一个方法来创建一个对象),你可以从一个对象得到一个接口,如果那个对象支持的话。因为所有的接口都是由一个类实现的,那么它们可以做不同的事情,但最终它们所做的事情取决于对象是什么,因此您又回到了必须知道类的问题上。
如果你想创建对象,你必须知道你正在创建的对象的类。接口可以提供一个方法来返回实现接口的对象的类,允许你创建更多的对象,但是你也可以使用那个类。
如果不同的类型没有共同的祖先,那么可以指定T必须支持接口,但是你仍然用一个类示例化
TMutliBLOCK<T>
。因为接口总是由一个类实现的,所以T总是从TObject
派生的,所以它总是支持Create
。问题是你不能't调用T.Create
,除非IBlock
包含Create ...的定义这意味着你可以有一个TMulitBLOCK和一个TMultiBLOCK,但是每个都保存你为它声明的对象。如果它们不是从一个公共类继承的,那么你就不能将
T
的类型限制为那个公共祖先。您可以检查正在使用的类型是否支持构造函数中的接口,然后将其限制为
TObject
。要调用
IBlock
的成员,您需要为每个对象获取一个接口指针。请记住,根据不同实现类中的实现,当接口引用超出范围时,对象可能会删除自己。为了防止这种情况发生,您可能希望在创建对象时将接口引用与对象一起存储,以便引用计数保持在0以上。如果你可以组织代码,使所有成员都派生自一个公共祖先,那么你就可以将你的
TMultiBLOCK<T>
限制到那个公共祖先,而不是一个公共接口。