Delphi: A generic list of generic-descendants and taking a generic as a parameter
I struggle a little with the understanding of generics and how they can and can not be used.
I have a generic class TControlMediator like this:
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;
I then make 'concret' subclasses for each control type that I want to mediate:
TEditMediator = class(TControlMediator<TEdit, string>)
public
function GetValue: string; override;
procedure SetValue(Value: string); override;
end;
So far, everything seems to work OK. Problems arise, though, when I want a list of TControlMediator descendants, or taking a TControlMediator 开发者_如何学编程as an parameter to a method:
TViewMediator = class
private
FControlMediators: TList<TControlMEdiator<C, T>>;
public
procedure registerMediator(AControlMediator: TControlMediator<C, T>);
procedure unregisterMediator(AControlMediator: TControlMediator<C, T>);
end;
The compiler stops with fatal errors:
[DCC Error] mediator.pas(23): E2003 Undeclared identifier: 'C'
[DCC Error] mediator.pas(28): E2007 Constant or type identifier expected
Do anybody have any clues on how this is supposed to be done?
Delphi has no covariance or contravariance on its generic types. Your generic types must use actual types as parameters. In other words, this:
TViewMediator = class
private
FControlMediators: TList<TControlMEdiator<C, T>>;
public
procedure registerMediator(AControlMediator: TControlMediator<C, T>);
procedure unregisterMediator(AControlMediator: TControlMediator<C, T>);
end;
...won't work because C and T are not generic type arguments to TViewMediator
or actual types.
TControlMediator<TEdit, string>
is a type. TList<TControlMEdiator<C, T>>
, when there are no types C
or T
in scope is not a type. You can't use a generic type placeholder in an instantiation of a generic type unless those placeholders are in scope as generic arguments to the containing generic type or method.
精彩评论