Réduisez votre empreinte de code Rust et augmentez sa robustesse avec des types génériques.

Il existe toujours des niveaux d'incertitude lors du développement d'applications, ce qui peut entraîner des erreurs, en particulier si vos fonctions acceptent des types d'arguments spécifiques. Pour réduire les erreurs dues aux incertitudes, vous pouvez utiliser les génériques. Les génériques fournissent des fonctionnalités pour créer des classes, des fonctions et des structures de données pour travailler avec différents types.

À l'aide de génériques, vous pouvez créer et définir des algorithmes et des structures de données pouvant fonctionner sur plusieurs types sans écrire de code complexe et sans implémentations distinctes pour chaque type. Les génériques améliorent la réutilisabilité et l'efficacité du code tout en maintenant la sécurité et les performances du type.

Utilisation de types génériques dans Rust

Le type générique de Rust peut interagir avec autres types de données Rust. Vous définirez des types génériques avec des crochets angulaires (<>), suivis de deux paramètres ou plus.

instagram viewer

Voici un générique définition de structure qui prend deux paramètres de type générique :

structureIndiquer {
// T et U sont des paramètres de type générique que les champs x et y vont
// assume sur l'instanciation
x: T,
y: vous,
}

Dans le Indiquer structure, T, et tu sont des paramètres de type générique.

Vous pouvez remplacer les paramètres de type générique par n'importe quel type de données lors de l'instanciation :

fnprincipal() {
laisser mon_point = Point { x: Chaîne::depuis("Bonjour"), y: Chaîne::depuis("monde") };

imprimez !(
"La valeur x de my_point est {} et la valeur y est {}.",
mon_point.x,
mon_point.y
);
}

Le mon point variable est une instance de Indiquer struct initialisé avec des types de chaîne. Le compilateur Rust déduit les types concrets de J et tu sur la base des valeurs d'instanciation.

Limites de trait pour les types génériques

Les types génériques Rust peuvent utiliser des limites de traits pour assurer la sécurité des types. Les traits sont des collections de méthodes que les types peuvent implémenter pour présenter certains comportements définis pour le trait.

Les limites de trait spécifient qu'un type générique doit implémenter un ou plusieurs traits.

Voici un exemple de fonction générique qui renvoie la plus grande de deux valeurs avec une limite de trait qui garantit que les types comparés implémentent le trait :

// Maximum est un trait qui définit une méthode pour évaluer le maximum de deux
// les types
traitMaximum {
fnmaximum(soi, autre: Soi) -> Soi;
}

// Implémente le trait `Maximum` pour tous les types qui implémentent le
// Caractéristique `OrdPartiel`.
mettre en œuvreOrdrePartiel> Maximum pour T {
fnmaximum(soi, autre: Soi) -> Soi {
// renvoie `self` s'il est supérieur à `other`; sinon, retournez
// `autre.`
sisoi > autre {
soi
} autre {
autre
}
}
}

fnprincipal() {
laisser un = 5;
laisser b = 10;
laisser le plus grand = Maximum:: max (a, b);
imprimez !("La plus grande valeur est {}", le plus grand);
}

Le Maximum trait a un maximum méthode qui renvoie la plus grande de deux valeurs du même type. Tout type qui implémente le OrdrePartiel trait implémente le Maximum trait.

Le maximum méthode prend deux valeurs de la Soi type—se référant au type implémentant le Maximum trait—et compare les valeurs.

Le principal La fonction compare deux variables à l'aide de la maximum méthode et imprime le plus grand.

Contraintes pour les types génériques

Les contraintes sont similaires aux limites de trait, mais elles vous permettent de spécifier des exigences supplémentaires sur les types que vous utilisez comme paramètres de type.

Si vous souhaitez créer une fonction générique qui accepte les types pour la conversion de chaînes, vous pouvez utiliser une contrainte pour vous assurer que le paramètre de type implémente un trait.

// ToString est un trait avec une méthode de conversion de chaîne
traitToString {
fnto_string(&soi) -> Chaîne;
}

// to_string est une fonction générique qui prend une valeur de n'importe quel type qui
// implémente le trait ToString
fnto_stringToString>(valeur: T) -> Chaîne {
value.to_string()
}

Le to_string Le paramètre de valeur doit implémenter le ToString trait, qui garantit que vous pouvez convertir des valeurs de type J enchaîner avec le to_string méthode.

Les types génériques sont utiles pour travailler avec des traits

Les types génériques de rouille sont puissants et il existe des domaines à améliorer. Un domaine d'intérêt critique est l'amélioration des performances du code générique. Actuellement, le système de type de Rust peut imposer une surcharge au code générique, ralentissant les performances.

Les types génériques sont bénéfiques pour travailler avec des traits. À l'aide de types génériques, vous pouvez créer des objets de trait qui fonctionnent avec n'importe quel type implémentant un trait pour rendre vos méthodes plus flexibles.