ProgrammationDéveloppeur Rust / Développeur Backend

Qu'est-ce que les constructeurs et les méthodes de fabrique en Rust (par exemple, new, with_capacity), comment les mettre en œuvre correctement et quelles erreurs rencontrent les débutants ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

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 :

  • La fonction associée n'est pas liée à des traits ou à un objet, elle est appelée via ::.
  • Elle peut retourner soit self, soit Result<Self, E> — pratique pour les constructeurs pouvant échouer.
  • Il est possible de réaliser différentes fabriques (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 }) } } }

Question piège.

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 } }

Exemples d'erreurs réelles dues à une mauvaise compréhension du sujet.


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_str sans 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.