In Rust kann die Konstruktion type verwendet werden, um einen Alias für einen bestehenden Typ zu erstellen. Zum Beispiel:
type Kilometer = i32; fn add_distance(x: Kilometer, y: Kilometer) -> Kilometer { x + y }
Kilometer ist einfach ein weiteres Name für i32; der Compiler unterscheidet diese Typen nicht, und sie sind vollständig austauschbar.
Newtype-Pattern ist die Erstellung einer neuen Wrapper-Struktur für einen bestehenden Typ:
struct Kilometer(i32); // ein separater neuer Typ fn add_distance(x: Kilometer, y: Kilometer) -> Kilometer { Kilometer(x.0 + y.0) }
Jetzt sind Kilometer und i32 verschiedene Typen, die nicht verwechselt werden können.
Die Wahl zwischen diesen Ansätzen hängt von den Anforderungen an Sicherheit und Lesbarkeit ab. Für öffentliche APIs und insbesondere typensichere Maßeinheiten verwenden Sie Newtype.
Was ist der Unterschied zwischen
typeAlias und Newtype-Pattern in Rust? Kann man die Operationen für einen Typalias durch die Implementierung eines Traits einschränken?
Es wird oft geantwortet, dass Alias zur Zugriffskontrolle und Einschränkung von Operationen verwendet werden können, aber das ist nicht der Fall – ein Alias erzeugt keinen neuen Typ, und daher können keine einzigartigen Traits für ihn implementiert werden. Nur das Newtype-Pattern ist ein separater Typ, für den ein einzigartiges Verhalten implementiert werden kann.
type UserId = u64; struct UserIdNew(u64); trait Foo { fn foo(&self); } // Foo für UserId kann nicht implementiert werden, weil es einfach u64 ist. // Für UserIdNew ist es möglich.
Geschichte
In einem Projekt wurden Entfernungen in Metern und Millimetern mit Hilfe von Alias gemessen:
type Millimeter = u32; type Meter = u32;Im endgültigen Code wurden versehentlich Millimeter und Meter addiert, was zu Berechnungsfehlern führte. Die Typisierung funktionierte nicht – der Compiler hat das nicht erkannt. Wir wechselten zu Newtype, und das Problem verschwand.
Geschichte
In einer offenen API wurden Aliase für die Identifikatoren verschiedener Entitäten verwendet (
type UserId = u64;,type OrderId = u64;). Es kam zu Verwirrung: Jemand vertauschte die Parameter, und ein Bug gelangte aufgrund der Unfähigkeit, sie durch Typen zu unterscheiden, in die Produktion.
Geschichte
Ein Entwickler versuchte, ein einzigartiges Verhalten des Traits Display für einen Typalias zu implementieren:
type MyType = String; impl Display für MyType { ... }Der Compiler gab einen Fehler aus: "cannot implement trait for type alias". Das Problem wurde durch das Newtype-Pattern gelöst.