Rust n'a pas de constructeurs spéciaux comme en C++/Java. En général, un constructeur est implémenté comme une fonction associée (par exemple, new). Caractéristiques importantes :
::.Result<Self, E> — pratique pour les constructeurs pouvant échouer.with_capacity, from_str, options personnalisées).Exemple de constructeur de base :
struct Point { x: i32, y: i32 } impl Point { pub fn new(x: i32, y: i32) -> Self { Point { x, y } } }
Exemple de constructeur pouvant échouer :
impl Point { pub fn try_new(x: i32, y: i32) -> Result<Self, String> { if x < 0 || y < 0 { Err("Les coordonnées doivent être non négatives".to_string()) } else { Ok(Point { x, y }) } } }
Quel type de fonction doit être utilisé pour un constructeur : une fonction ordinaire, une méthode ou une fonction associée, et pourquoi ?
Beaucoup répondent : "méthode". Mais en Rust, les constructeurs ne sont que des fonctions associées (sans self), car l'instance n'existe pas encore et il est impossible d'appeler une méthode ordinaire.
struct Foo; impl Foo { // fonction associée, pas méthode pub fn new() -> Self { Foo } }
Histoire
Un programmeur a implémenté le constructeur comme une méthode :
impl Point { pub fn make(&self, x: i32, y: i32) -> Self { ... } }Cela n'a pas de sens et est déroutant : pour créer un objet, il faut un objet qui n'existe pas encore ! Le développeur était perdu sur la façon d'appeler cette méthode. Corrigé en une fonction statique.
Histoire
Erreur classique : retourner Option<Self> pour un constructeur pouvant échouer sans avertissement, ce qui entraîne l'oubli d'erreurs en cascade. Après avoir retourné Result<Self, E>, il est devenu possible de rendre les erreurs plus explicites.
Histoire
Implémentation de fabriques du type
from_parts,from_strsans utiliser le trait From/FromStr. En conséquence, les mécanismes de conversion standard (par exemple,str.parse::<MyType>()) ne fonctionnaient pas. Après avoir détecté l'erreur, FromStr a été intégré et la compatibilité du code avec les bibliothèques de l'écosystème a été améliorée.