Le monde des génériques
Commençons par le monde des génériques: la fonction d'identité.
La fonction d'identité est une fonction qui renvoie tout ce qui est transmis.
Vous pouvez le penser de la même manière que la commande
echo.
Sans génériques, nous devrions soit donner à la fonction identité un type spécifique:
Ou, nous pourrions décrire la fonction d'identité en utilisant le type
any :
Bien que
any soit certainement générique en ce sens que la fonction acceptera n'importe quel type pour le type
arg,
nous perdons en fait les informations relatives à ce type lorsque le retour de la fonction a eu lieu.
Si nous avons passé un nombre, la seule information dont nous disposons est que tout type pourrait être retourné.
Au lieu de cela, nous avons besoin d'un moyen de capturer le type de l'argument de manière à pouvoir également l'utiliser pour indiquer ce qui est renvoyé.
Ici, nous allons utiliser une variable de type, un type spécial de variable qui fonctionne sur des types plutôt que sur des valeurs.
Nous avons maintenant ajouté une variable de type
T à la fonction
identity.
Ce
T nous permet de capturer le type fourni par l'utilisateur (nombre, par exemple), afin que nous puissions utiliser ces informations ultérieurement.
Ici, nous utilisons à nouveau
T comme type de retour.
Lors de l'inspection, nous pouvons maintenant voir que le même type est utilisé pour
l'argument et le type de retour. Cela nous permet de véhiculer ces informations de type d'un côté et de l'autre de la fonction.
Nous disons que cette version de la fonction
identity est générique, car elle fonctionne sur plusieurs types. Contrairement à l'utilisation de
any,
elle est tout aussi précise (c'est-à-dire qu'elle ne perd aucune information) comme la première fonction
identity qui utilisait des nombres
pour l'argument et le type renvoyés.
Une fois que nous avons écrit la fonction
identity générique, nous pouvons l'appeler de deux manières. La première consiste à transmettre
tous les arguments, y compris l'argument type, à la fonction :
Ici, nous avons explicitement défini
T comme chaîne de l'un des arguments de l'appel de la fonction, noté en utilisant
<> autour des arguments plutôt que
().
La deuxième façon est peut-être aussi la plus courante. Ici, nous utilisons l'inférence d'argument de type; autrement dit,
nous voulons que le compilateur définisse automatiquement la valeur de
T pour nous en fonction du type de l'argument que nous transmettons :
Notez que nous n'avions pas à indiquer explicitement le type dans les crochets angulaires (
<>);
le compilateur a juste regardé la valeur "
myString", et a défini
T sur son type.
Bien que l'inférence d'argument de type puisse être
un outil utile pour garder le code plus court et plus lisible, vous devrez peut-être explicitement passer les arguments de type
comme nous l'avons fait dans l'exemple précédent lorsque le compilateur ne parvient pas à inférer le type, comme cela peut arriver dans des exemples plus complexes.