Historisch gesehen war eines der Prinzipien von Rust die Gewährleistung der Typensicherheit und das Fehlen von impliziten Umwandlungen, die zu Laufzeitfehlern führen können. Um den Code jedoch zu vereinfachen, werden teilweise automatische Umwandlungen über Deref Coercion und die Traits From/Into implementiert, um die Arbeit mit Referenzen, smarten Zeigern zu erleichtern und universelle APIs zu ermöglichen.
Das Problem tritt auf, wenn automatische Umwandlungen Verwirrung stiften können, zum Beispiel beim Übergeben von &String, wo &str erwartet wird. Es wird Deref::deref versteckt aufgerufen, was manchmal zu unerwarteten Konsequenzen führt (zum Beispiel bei der Änderung des Typs der übergebenen Parameter). Auch gibt es die Frage nach direkter und expliziter Typumwandlung mittels as.
Lösung: Rust implementiert strenge Regeln für Deref-Coercion für smarte Zeiger (Box, Rc, Arc) und Strings (&String zu &str, &Vec zu &slice) auf Compiler-Ebene. Für explizite Umwandlungen sind die Traits From, Into, TryFrom, TryInto und as für grundlegende Umwandlungen vorgesehen. Statische Typisierung und das Verbot von impliziten Umwandlungen helfen, Fehler zu vermeiden.
Beispielcode:
fn print_text(text: &str) { println!("{}", text); } let s = String::from("Hello!"); print_text(&s); // s: String, &s: &String, automatische Umwandlung zu &str
Wichtige Merkmale:
Funktioniert Deref Coercion für eigene Typen, wenn man Deref manuell implementiert?
Ja, wenn Sie das Trait Deref für Ihren Typ implementieren, kann der Compiler automatisch umwandeln, zum Beispiel Ihre Wrapper in den Zieltyp innerhalb der Funktionssignatur, die die entsprechende Referenz erwartet.
Kann Deref Coercion auch für Werte und nicht für Referenzen stattfinden?
Nein, die automatische Dereferenzierung erfolgt nur beim Übergeben von Referenzen und nur, wenn der Typ Deref implementiert.
Welche Einschränkungen hat die Typumwandlung über as bei der Arbeit mit Zahlen und Enums?
as garantiert keine Sicherheit: Die Umwandlung zwischen Zahltpyen kann zu Überläufen oder Datenverlust führen, und bei Enums resultiert dies in nicht-semantischen Werten (zum Beispiel zu einem ungültigen Enum-Zweig).
Ein Anfänger schreibt eine Funktion, die &String entgegennimmt, und kann nicht direkt &str verwenden, macht überall text.to_string() aus einem String. Das ist speicherverschwendend und in Bezug auf die Leistung ungünstig.
Vorteile:
Nachteile:
Eine Funktion nimmt ein Argument des Typs &str entgegen, wodurch sie mit jedem Typ aufgerufen werden kann, der Dereferenzierung oder Umwandlung unterstützt: &str, &String, String-Literale. Es sind keine zusätzlichen Allokationen erforderlich.
Vorteile:
Nachteile: