Rust heeft geen speciale constructors zoals in C++/Java. Een constructor wordt meestal geïmplementeerd als een geassocieerde functie (bijvoorbeeld, new). Belangrijke kenmerken:
::.Result<Self, E> retourneren - handig voor fallible constructors.with_capacity, from_str, aangepaste versies).Voorbeeld van een basisconstructor:
struct Point { x: i32, y: i32 } impl Point { pub fn new(x: i32, y: i32) -> Self { Point { x, y } } }
Voorbeeld van een fallible constructor:
impl Point { pub fn try_new(x: i32, y: i32) -> Result<Self, String> { if x < 0 || y < 0 { Err("Coördinaten moeten niet-negatief zijn".to_string()) } else { Ok(Point { x, y }) } } }
Welk type functie moet worden gebruikt voor een constructor: een gewone functie, een methode of een geassocieerde functie, en waarom?
Velen antwoorden: "methode". Maar in Rust zijn constructors - alleen geassocieerde functies (zonder self), omdat er nog geen exemplaar is en een gewone methode niet kan worden aangeroepen.
struct Foo; impl Foo { // geassocieerde functie, geen methode pub fn new() -> Self { Foo } }
Verhaal
Een programmeur implementeerde de constructor als een methode:
impl Point { pub fn make(&self, x: i32, y: i32) -> Self { ... } }Dit is onlogisch en verwarrend: voor het maken van een object is een object nodig dat nog niet bestaat! De ontwikkelaar raakte in de war over hoe deze methode aan te roepen. Het werd gecorrigeerd naar een statische functie.
Verhaal
Een klassieke fout: retourneer Option<Self> voor een fallible constructor zonder waarschuwing, waardoor cascadefouten worden gemist. Nadat Result<Self, E> werd geretourneerd, werd het mogelijk om fouten duidelijker weer te geven.
Verhaal
Implementatie van factories zoals
from_parts,from_strzonder gebruik te maken van het trait From/FromStr. Hierdoor werkten de standaardconversiemechanismen niet (bijvoorbeeld,str.parse::<MyType>()). Na het ontdekken van de fout werd FromStr geïmplementeerd en werd de compatibiliteit van de code met ecosystembibliotheken verhoogd.