我对泛型的理解以及它们如何能够和不能被使用有点挣扎。
我有一个像这样的通用类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;
然后,我为每个我想调解的控件类型制作'concret'子类:
TEditMediator = class(TControlMediator<TEdit, string>)
public
function GetValue: string; override;
procedure SetValue(Value: string); override;
end;
到目前为止,一切似乎都运转正常。但是,当我想要一个TControlMediator后代列表,或者将TControlMediator作为方法的参数时出现问题:
TViewMediator = class
private
FControlMediators: TList<TControlMEdiator<C, T>>;
public
procedure registerMediator(AControlMediator: TControlMediator<C, T>);
procedure unregisterMediator(AControlMediator: TControlMediator<C, T>);
end;
编译器因致命错误而停止:
[DCC Error] mediator.pas(23): E2003 Undeclared identifier: 'C'
[DCC Error] mediator.pas(28): E2007 Constant or type identifier expected
有没有人知道如何做到这一点?
答案 0 :(得分:6)
德尔福对其泛型类型没有协方差或逆变。您的泛型类型必须使用实际类型作为参数。换句话说,这个:
TViewMediator = class
private
FControlMediators: TList<TControlMEdiator<C, T>>;
public
procedure registerMediator(AControlMediator: TControlMediator<C, T>);
procedure unregisterMediator(AControlMediator: TControlMediator<C, T>);
end;
...将无效,因为C和T不是TViewMediator
或实际类型的泛型类型参数。
TControlMediator<TEdit, string>
是一种类型。 TList<TControlMEdiator<C, T>>
,当范围中没有类型C
或T
时,不是类型。您不能在泛型类型的实例化中使用泛型类型占位符,除非这些占位符在作为包含泛型类型或方法的泛型参数的范围内。