In Rust kan de constructie type worden gebruikt om een alias voor een bestaand type te maken. Bijvoorbeeld:
type Kilometers = i32; fn add_distance(x: Kilometers, y: Kilometers) -> Kilometers { x + y }
Kilometers is gewoon een andere naam voor i32; de compiler maakt geen onderscheid tussen deze types, en ze zijn volledig uitwisselbaar.
Newtype pattern is het creëren van een nieuwe wrapperstructuur voor een bestaand type:
struct Kilometers(i32); // aparte nieuwe type fn add_distance(x: Kilometers, y: Kilometers) -> Kilometers { Kilometers(x.0 + y.0) }
Nu zijn Kilometers en i32 verschillende types, en ze kunnen niet door elkaar gehaald worden.
De keuze tussen deze benaderingen hangt af van de eisen voor veiligheid en leesbaarheid. Voor open API's, en vooral voor typeveilige eenheden van maat, gebruik newtype.
Wat is het verschil tussen
typealias en newtype pattern in Rust? Kun je operaties voor een type alias beperken door een trait te implementeren?
Vaak wordt gezegd dat een alias kan worden gebruikt voor toegangscontrole en het beperken van operaties, maar dat is niet zo - een alias creëert geen nieuw type, wat betekent dat je er geen unieke traits voor kunt implementeren. Alleen het newtype pattern is een apart type waarvoor unieke gedrag kan worden geïmplementeerd.
type UserId = u64; struct UserIdNew(u64); trait Foo { fn foo(&self); } // Foo implementeren voor UserId kan niet, omdat het gewoon u64 is. // Voor UserIdNew kan dat.
Verhaal
In het project werden afstanden in meters en millimeters gemeten met behulp van aliassen:
type Millimeters = u32; type Meters = u32;In de uiteindelijke code werden per ongeluk millimeters met meters opgeteld, wat leidde tot rekenfouten. Typisering werkte niet - de compiler ving dit niet. We schakelden over naar newtype en het probleem verdween.
Verhaal
In de open API werden aliassen gebruikt voor identificaties van verschillende entiteiten (
type UserId = u64;,type OrderId = u64;). Er ontstond verwarring: iemand verwisselde parameters, en een bug kwam in productie vanwege het onvermogen om ze van elkaar te onderscheiden op basis van type.
Verhaal
Een ontwikkelaar probeerde uniek gedrag van de trait Display voor een type alias te implementeren:
type MyType = String; impl Display voor MyType { ... }De compiler gaf een foutmelding: "kan geen trait implementeren voor type alias". Het probleem werd opgelost via het newtype pattern.