I. Introduction▲
I-A. Prérequis▲
Ce tutoriel n'est pas destiné au débutant Delphi ou à celui qui n'a jamais pratiqué la programmation orientée objet. Il requiert de bien connaître le langage Delphi auparavant, et une connaissance non négligeable de la POO.
Concernant les génériques, aucune connaissance n'est nécessaire à la bonne compréhension et appréhension de ce tutoriel. Mais, au vu du nombre d'articles existant sur les génériques dans d'autres langages, je ne couvrirai pas en détail des questions du type « Comment bien utiliser les génériques ? ». La prochaine section introduira rapidement le lecteur à la notion de générique, mais si vous ne savez pas encore ce que c'est, la meilleure compréhension viendra de la suite du tutoriel, par l'exemple.
Voici quelques articles traitant des génériques dans d'autres langages/plateformes. Les concepts sont toujours les mêmes, et une grande partie de la mise en œuvre également.
- Les génériques sous Delphi .NETLes génériques sous Delphi .NET, par Laurent Dardenne par Laurent Dardenne ;
- Generics avec Java Tiger 1.5.0Generics avec Java Tiger 1.5.0, par Lionel Roux par Lionel Roux ;
- Cours de C/C++ - Les templateCours de C/C++ - Les template, par Christian Casteydes par Christian Casteyde.
I-B. Que sont les génériques ?▲
Les génériques sont parfois appelés paramètres génériques, un nom qui permet déjà bien mieux de les introduire. Contrairement au paramètre d'une fonction (argument), qui a une valeur, le paramètre générique est un type. Et un paramètre générique paramétrise une classe, une interface, un record, ou, moins souvent, une méthode.
Pour donner immédiatement une idée plus claire, voici un extrait de la classe TList<T>, que vous pourrez trouver dans l'unité Generics.Collections.pas.
Eh oui, il est possible d'avoir des points dans le nom d'une unité (hors celui du .pas, j'entends). Cela n'a rien à rien à voir avec la notion d'espace de noms de .NET ni celle de package de Java. C'est juste que le . a même valeur qu'un _ à ce niveau : il fait partie du nom, tout simplement.
type
TList<T> = class
(TEnumerable<T>)
// ...
public
// ...
function
Add(const
Value: T): Integer
;
procedure
Insert(Index
: Integer
; const
Value: T);
function
Remove(const
Value: T): Integer
;
procedure
Delete(Index
: Integer
);
procedure
DeleteRange(AIndex, ACount: Integer
);
function
Extract(const
Value: T): T;
procedure
Clear;
property
Count: Integer
read
FCount write
SetCount;
property
Items[Index
: Integer
]: T read
GetItem write
SetItem; default
;
end
;
Vous pouvez directement observer l'étrangeté du type T. Mais est-ce vraiment un type ? Non, c'est un paramètre générique. Avec cette classe, si j'ai besoin d'une liste d'entiers, j'utilise TList<Integer>, au lieu d'une « simple » TList avec de nombreux transtypages nécessaires dans le code !
Les génériques permettent donc, en quelque sorte, de déclarer une série de classes (potentielles) en une seule fois, ou plus exactement de déclarer un modèle de classe, mais avec un (ou plusieurs) type paramétré qui pourra être changé à loisir. À chaque instanciation avec un nouveau type réel, c'est comme si vous écriviez toute une nouvelle classe, à partir du modèle, et donc rendez réelle une de ces classes potentielles.
Comme je l'ai dit, je ne m'étendrai pas sur le pourquoi du comment des génériques. Je vais immédiatement embrayer sur leur utilisation au quotidien. Si vous n'avez encore rien compris, ce n'est pas grave : tout va s'éclaircir petit à petit. Vous pouvez aussi consulter le tutoriel Les génériques sous Delphi .NETLes génériques sous Delphi .NET, par Laurent Dardenne de Laurent Dardenne.