In Rust ist es erlaubt, ein Trait für einen Typ nur dann zu implementieren, wenn:
Diese Bedingungen werden als Orphan-Regel bezeichnet. Sie schützt vor Konflikten im Falle unabhängiger Implementierungen desselben Traits für denselben Typ in verschiedenen Crates.
Wenn Sie ein externes Trait für einen externen Typ implementieren möchten, ist dies direkt nicht möglich. Normalerweise wird das Muster "newtype" verwendet: Den Typ in eine eigene Struktur innerhalb des Crates zu wickeln und dann das Trait für den eigenen Typ zu implementieren.
Beispiel:
// Externer Typ und externes Trait (nicht in unserem Crate) // struct ExternalType; trait ExternalTrait { ... } struct MyWrapper(ExternalType); impl ExternalTrait for MyWrapper { /* ... */ } // Jetzt arbeiten wir mit der Wrapper
Frage: Kann man ein externes Trait für einen externen Typ implementieren, wenn beide öffentlich sind, über use und impl?
Falsche Antwort: Ja, es ist ausreichend, einfach impl in unserem Crate zu deklarieren, und es wird funktionieren.
Richtige Antwort: Nein, der Compiler erlaubt das nicht. Ein Trait kann nur implementiert werden, wenn das Trait oder der Typ im aktuellen Crate deklariert sind. Andernfalls gibt es einen Orphan-Regel-Fehler.
Beispiel für einen Fehler:
// extern crate other; // impl Display for other::ExternalType { ... } // Orphan-Regel-Fehler
Geschichte
Im Team wurde Unterstützung für einen externen Logger durch impl eines externen Traits benötigt. Der Versuch, ihn für einen externen Typ zu implementieren, führte zu einem Orphan-Regel-Fehler und langen Diskussionen über die Gründe. Letztendlich musste die Architektur auf Newtype umgestaltet werden.
Geschichte
In einem Open-Source-Projekt wurde beschlossen, Debug für eine Struktur aus einer anderen Bibliothek zu implementieren, was durch die Orphan-Regel nicht erlaubt war. In der Folge mussten die Benutzer mit umständlichen Workarounds und eigenen Wrappers arbeiten.
Geschichte
Schwerwiegender Fehler: Bei dem Versuch, FromStr für einen externen Enum zur Analyse aus einer Zeichenkette zu implementieren, wurde der Orphan-Regel-Fehler vom Compiler nicht akzeptiert. Der Entwickler "löste" das Problem durch unsichere Speicherumwandlungen, was zu UB in der Produktion führte.