delphi 使用泛型类多次生成Obj

ggazkfy8  于 2023-02-04  发布在  其他
关注(0)|答案(1)|浏览(188)

我在泛型和构造函数方面遇到了一些麻烦。
我想有一个泛型类,可以处理(和创建)同一个类的多个对象。此外,我有一些代码,我想使用任何具体的类实际上是。
我认为泛型是一个很好的解决方案,但我不太确定。

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类型的每个类实现的接口。

i86rm4rw

i86rm4rw1#

用OOP的术语来说,接口是一个纯粹的抽象定义。它可以由许多不同的类来实现。你不能从接口创建对象(除非接口给你一个方法来创建一个对象),你可以从一个对象得到一个接口,如果那个对象支持的话。因为所有的接口都是由一个类实现的,那么它们可以做不同的事情,但最终它们所做的事情取决于对象是什么,因此您又回到了必须知道类的问题上。
如果你想创建对象,你必须知道你正在创建的对象的类。接口可以提供一个方法来返回实现接口的对象的类,允许你创建更多的对象,但是你也可以使用那个类。
如果不同的类型没有共同的祖先,那么可以指定T必须支持接口,但是你仍然用一个类示例化TMutliBLOCK<T>。因为接口总是由一个类实现的,所以T总是从TObject派生的,所以它总是支持Create。问题是你不能't调用T.Create,除非IBlock包含Create ...的定义
这意味着你可以有一个TMulitBLOCK和一个TMultiBLOCK,但是每个都保存你为它声明的对象。如果它们不是从一个公共类继承的,那么你就不能将T的类型限制为那个公共祖先。
您可以检查正在使用的类型是否支持构造函数中的接口,然后将其限制为TObject

TMultiBLOCK<T: class> = class(TObject)
protected
  blocks:  TArray<T>;

public
  constructor Create(AOwner: pSomeObject; nSize: Integer);
end;

constructor TMultiBLOCK<T>.Create(AOwner: pSomeObject; nSize: Integer);
begin
  if(not Supports(T, IBlock)) then
    raise EInvalidCast.Create('Class '+T.ClassName+' must support IBlock')
  else
    ...
end;

要调用IBlock的成员,您需要为每个对象获取一个接口指针。请记住,根据不同实现类中的实现,当接口引用超出范围时,对象可能会删除自己。为了防止这种情况发生,您可能希望在创建对象时将接口引用与对象一起存储,以便引用计数保持在0以上。
如果你可以组织代码,使所有成员都派生自一个公共祖先,那么你就可以将你的TMultiBLOCK<T>限制到那个公共祖先,而不是一个公共接口。

相关问题