Delphi:泛型后代的通用列表,并将泛型作为参数

Veg*_*gar 3 delphi generics delphi-2010

我对于仿制药的理解以及它们如何能够和不能被使用有点挣扎.

我有一个通用类TControlMediator,如下所示:

TControlMediator<C, T> = class
private
  FMediatedComponent: C;
public
  constructor Create(ComponentToMediate: C);

  function GetValue: T; virtual; abstract;
  procedure SetValue(Value: T); virtual; abstract;

  property MediatedControl: C read FMediatedComponent;
end;
Run Code Online (Sandbox Code Playgroud)

然后我为每个我想调解的控件类型制作'concret'子类:

TEditMediator = class(TControlMediator<TEdit, string>)
public
  function GetValue: string; override;
  procedure SetValue(Value: string); override;
end;
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切似乎都运作正常.但是,当我想要一个TControlMediator后代列表,或者将TControlMediator作为方法的参数时,会出现问题:

TViewMediator = class
private
  FControlMediators: TList<TControlMEdiator<C, T>>;
public
  procedure registerMediator(AControlMediator: TControlMediator<C, T>);
  procedure unregisterMediator(AControlMediator: TControlMediator<C, T>);
end;
Run Code Online (Sandbox Code Playgroud)

编译器因致命错误而停止:

[DCC Error] mediator.pas(23): E2003 Undeclared identifier: 'C'
[DCC Error] mediator.pas(28): E2007 Constant or type identifier expected
Run Code Online (Sandbox Code Playgroud)

有没有人知道如何做到这一点?

Cra*_*ntz 6

德尔福在其泛型类型上没有协方差或逆变.您的泛型类型必须使用实际类型作为参数.换句话说,这个:

TViewMediator = class
private
  FControlMediators: TList<TControlMEdiator<C, T>>;
public
  procedure registerMediator(AControlMediator: TControlMediator<C, T>);
  procedure unregisterMediator(AControlMediator: TControlMediator<C, T>);
end;
Run Code Online (Sandbox Code Playgroud)

...将无效,因为C和T不是通用类型参数TViewMediator或实际类型.

TControlMediator<TEdit, string>是一种类型.TList<TControlMEdiator<C, T>>,当没有类型CT范围不是一个类型.您不能在泛型类型的实例化中使用泛型类型占位符,除非这些占位符在作为包含泛型类型或方法的泛型参数的范围内.

  • 您可以为泛型类型指定非泛型父类型,并使列表成为列表. (2认同)