2009-10-27 8 views
3

Je me débats un peu avec la compréhension des génériques et comment ils peuvent et ne peuvent pas être utilisés.Delphi: Une liste générique de génériques-descendants et de prendre un générique comme un paramètre

J'ai un TControlMediator de classe générique comme ceci:

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; 

Je fais alors des sous-classes « de béton pompe à béton » pour chaque type de contrôle que je veux servir de médiateur:

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

Jusqu'à présent, tout semble fonctionne bien. Des problèmes se posent, cependant, quand je veux une liste des descendants TControlMediator, ou de prendre un TControlMediator comme paramètre à une méthode:

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

Le compilateur arrête avec des erreurs fatales:

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

Avez-ce que quelqu'un a une des indices sur la façon dont cela est censé être fait?

Répondre

6

Delphi n'a aucune covariance ou contravariance sur ses types génériques. Vos types génériques doivent utiliser des types réels en tant que paramètres. En d'autres termes, ceci:

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

... ne fonctionnera pas parce que C et T ne sont pas des arguments de type générique ou à TViewMediator types réels.

TControlMediator<TEdit, string> est un type. TList<TControlMEdiator<C, T>>, lorsqu'il n'y a aucun type C ou T dans la portée n'est pas un type. Vous ne pouvez pas utiliser un espace réservé de type générique dans une instance d'instanciation d'un type générique sauf si ces espaces réservés sont dans la portée en tant qu'arguments génériques du type ou de la méthode générique conteneur.

+0

Donc, je suis fondamentalement foutu, alors? Ma liste doit être un bon vieux TList de TObjects, et il n'y a aucun moyen de lancer les objets dans un TControlMediator afin que je puisse appeler des méthodes dessus? – Vegar

+0

Je ne peux pas dire si vous êtes foutu jusqu'à ce que je comprenne exactement pourquoi vous voulez faire cela. Pourriez-vous juste paramétrer comme 'TViewMediator '? –

+0

Je veux enregistrer des médiateurs de type différent comme: MyViewMediator.RegisterMediator (TEditMediator.create (someEdit)); MyViewMediator.RegisterMediator (TComboMediator.create (someCombo)); Plus tard, je veux boucler tous les médiateurs enregistrés et appeler une méthode sur eux. – Vegar

Questions connexes