ProgrammazioneSviluppatore Rust / Sviluppatore Backend

Che cosa sono i costruttori e i metodi factory in Rust (ad esempio, new, with_capacity), come implementarli correttamente e quali errori si incontrano nei principianti?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Rust non ha costruttori speciali come in C++/Java. Di solito, un costruttore viene implementato come funzione associata (ad esempio, new). Caratteristiche importanti:

  • La funzione associata non è legata a trait o oggetto ed è chiamata tramite ::.
  • Può restituire sia self che Result<Self, E> — utile per costruttori fallibili.
  • È possibile implementare diverse fabbriche (with_capacity, from_str, varianti personalizzate).

Esempio di costruttore base:

struct Point { x: i32, y: i32 } impl Point { pub fn new(x: i32, y: i32) -> Self { Point { x, y } } }

Esempio di costruttore fallibile:

impl Point { pub fn try_new(x: i32, y: i32) -> Result<Self, String> { if x < 0 || y < 0 { Err("Le coordinate devono essere non negative".to_string()) } else { Ok(Point { x, y }) } } }

Domanda trabocchetto.

Che tipo di funzione dovrebbe essere usato per un costruttore: funzione normale, metodo o funzione associata, e perché?

Molti rispondono: "metodo". Ma in Rust i costruttori sono solo funzioni associate (senza self), poiché l'istanza non esiste ancora e non è possibile chiamare un metodo normale.

struct Foo; impl Foo { // funzione associata, non metodo pub fn new() -> Self { Foo } }

Esempi di errori reali dovuti alla mancanza di conoscenza delle sottigliezze dell'argomento.


Storia

Un programmatore ha implementato un costruttore come metodo:

impl Point { pub fn make(&self, x: i32, y: i32) -> Self { ... } }

Questo è illogico e confuso: per creare un oggetto serve un oggetto che non esiste ancora! Lo sviluppatore si perdeva nel tentativo di chiamare questo metodo. È stato corretto in una funzione statica.


Storia

Errore classico: restituire Option<Self> per un costruttore fallibile senza avviso, il che ha portato a trascurare errori a cascata. Dopo aver restituito Result<Self, E>, è diventato possibile visualizzare gli errori in modo più chiaro.


Storia

Implementazione di fabbriche come from_parts, from_str senza utilizzare il trait From/FromStr. Di conseguenza, i meccanismi di conversione standard non funzionavano (ad esempio, str.parse::<MyType>()). Dopo aver scoperto l'errore, è stato implementato FromStr e aumentata la compatibilità del codice con le librerie dell'ecosistema.