Rust non ha costruttori speciali come in C++/Java. Di solito, un costruttore viene implementato come funzione associata (ad esempio, new). Caratteristiche importanti:
::.Result<Self, E> — utile per costruttori fallibili.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 }) } } }
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 } }
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_strsenza 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.