IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Les génériques avec Delphi 2009 Win32

Avec en bonus les routines anonymes et les références de routine


précédentsommairesuivant

IX. RTTI et génériques

En dernier chapitre de ce tutoriel, voici quelques informations sur ce que deviennent les RTTI avec les génériques. Si vous ne jouez jamais avec les RTTI, vous pouvez sauter entièrement ce chapitre. Ce n'est pas du tout une introduction aux RTTI.

IX-A. Les changements sur la pseudoroutine TypeInfo

Les RTTI, ça commence toujours par la pseudoroutine TypeInfo. Vous savez peut-être qu'on ne peut pas appeler cette pseudoroutine sur n'importe quel type ; exemple : les types pointeur. Et que, de ce fait, elle ne renvoie jamais nil.

Alors, peut-on appeler TypeInfo sur un type générique T ? La question est pertinente : T pourrait bien être un type pointeur (invalide pour TypeInfo), mais également un type entier par exemple (valide pour TypeInfo).

La réponse est oui, on peut appeler TypeInfo sur un type générique. Mais que se passe-t-il alors si T se trouve être un type qui n'a pas de RTTI ? Eh bien, dans ce cas, et dans ce cas seulement, TypeInfo renvoie nil.

Pour illustrer la chose, voici une petite méthode de classe qui affiche le nom et la sorte d'un type, mais via des génériques :

 
Sélectionnez
type
  TRTTI = class(TObject)
  public
    class procedure PrintType<T>; static;
  end;

class procedure TRTTI.PrintType<T>;
var
  Info: PTypeInfo;
begin
  Info := TypeInfo(T); // attention ! Info peut valoir nil ici

  if Info = nil then
    WriteLn('Ce type ne possède pas de RTTI')
  else
    WriteLn(Info.Name, #9, GetEnumName(TypeInfo(TTypeKind), Byte(Info.Kind)));
end;

On l'utilise de manière un peu particulière, dans le sens où le véritable paramètre de la routine PrintType est transmis en tant que type paramétré.

 
Sélectionnez
begin
  TRTTI.PrintType<Integer>;
  TRTTI.PrintType<TObject>;
  TRTTI.PrintType<Pointer>;
end;

Ce qui donne :

 
Sélectionnez
Integer  tkInteger
TObject  tkClass
Ce type ne possède pas de RTTI

IX-A-1. Une fonction TypeInfo plus générale

Il m'est déjà arrivé de regretter que TypeInfo ne puisse pas être appelée sur n'importe quel type, quitte à recevoir nil ; peut-être que vous aussi. Voici donc une petite méthode de remplacement qui fait ça, à base de génériques.

 
Sélectionnez
type
  TRTTI = class(TObject)
  public
    class procedure PrintType<T>; static;
    class function TypeInfo<T>: PTypeInfo; static;
  end;

class function TRTTI.TypeInfo<T>: PTypeInfo;
begin
  Result := System.TypeInfo(T);
end;

Que vous pouvez utiliser comme ceci :

 
Sélectionnez
Info := TRTTI.TypeInfo<Pointer>; // Info = nil
// au lieu de :
Info := TypeInfo(Pointer); // erreur ici, car Pointer n'a pas de RTTI

IX-B. Les types génériques ont-ils des RTTI ?

Il y a deux questions à se poser : est-ce que les types génériques non instanciés (avec donc un paramètre T non défini) ont des RTTI ? Et est-ce que les types génériques instanciés (donc où T a été remplacé par un type réel, comme Integer) ont des RTTI ?

Le plus facile pour le savoir est de l'essayer ;-) Vous pourrez observer, en testant, que seuls les types génériques instanciés ont des RTTI. En fait, c'est assez logique, dans la mesure où les types génériques non instanciés ne sont pas réellement des types, mais des modèles de type, et n'existent tout simplement plus du tout une fois passée la compilation.

On peut se demander quel nom on va trouver pour de tels types. Alors voici :

 
Sélectionnez
begin
  TRTTI.PrintType<TComparison<Integer>>;
  TRTTI.PrintType<TTreeNode<Integer>>;
end;

Ce qui donne :

 
Sélectionnez
TComparison<System.Integer>  tkInterface
TTreeNode<System.Integer>    tkClass

Ce qui montre que le nom comprend, entre chevrons, le nom complètement qualifié du type réel remplaçant le type générique.

Vous pouvez aussi remarquer qu'on obtient bien tkInterface pour le type référence de routine TComparison<T>, ce qui prouve bien que c'est une interface.

Voilà, ce sont les seuls changements apportés aux RTTI avec l'avènement des génériques. Je ne parle bien sûr pas d'autres changements apportés dans cette version, mais qui concernent les chaînes Unicode.


précédentsommairesuivant

Copyright © 2008 Sébastien Doeraene. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.