2015-09-14 4 views
11

Ich bin in Rust stabil eine Kiste API definieren (ab sofort Version 1.2) und ist perplex über Best Practices für meine eigenen strangartige Typen definieren.Wenn AsRef oder andere Umwandlungseigenschaften für strangartigen Typen verwenden

Zum Beispiel, ich habe einen Foo Typen, der eine Zeichenfolge umschließt.

pub struct Foo(String); 

Meine API verbirgt Bau von Foo Instanzen, und darüber hinaus, weil das Tupel Feld privat ist, kann die Anwendung nicht versehentlich einen ungültigen Foo Wert für sich selbst konstruieren. Das bedeutet, dass meine API die Anwendung so einschränkt, dass sie nur mit gültigen Foo Werten arbeitet. So weit, ist es gut.

Allerdings mag ich die Anwendung in der Lage sein, eine Foo Instanz zu verwenden, als ob es ein String-Sagen, es drucken, es Protokollierung in eine Datei schreiben, um es zu einer Dritt Kiste vorbei, die &str akzeptiert, eine Kopie über to_string() und Mutieren der Kopie, usw. kurz gesagt konstruieren, möchte ich die Anwendung auf die zugrunde liegenden String mit einem Verweis auf der Lage sein, „wegzuwerfen“ Foo -ness und arbeiten. Da die Anwendung die Raw-Zeichenfolge nicht zurück in eine Foo Instanz konvertieren kann, wird type-safety beibehalten.

Meine Frage ist: Welche Konvertierungsmerkmale, wenn überhaupt, sollte meine Kiste für Foo implementieren, damit die Anwendung Foo -ness "wegwerfen" und mit der zugrunde liegenden Zeichenfolge als eine rohe Zeichenfolge arbeiten? Es ist wichtig, dass Foo in &str konvertiert wird, um unnötiges Kopieren der zugrunde liegenden Zeichenfolge zu vermeiden.

Zum Beispiel, wie etwa?

impl AsRef<str> for Foo 

Ist das das Richtige? Ist es genug, um idiomatisch zu sein? Gibt es andere Conversion-Merkmale, die ich für Foo implementieren sollte?

Antwort

8

Wenn ein Fooist semantisch ein String ist, dann Umsetzung Deref<Target = str> (oder möglicherweise Deref<Target = String> und DerefMut) ist die wichtigste Sache zu tun. Das erlaubt &Foo-&str, zu zwingen, so dass Sie Dinge wie &*foo schreiben kann eine &str aus einem Foo zu bekommen, und foo.starts_with("bar") und solche, Aufrufen von Methoden, die auf str definiert sind.

AsRef Implementierung wird auch für einige Dinge von Vorteil sein. Borrow ist eine andere Sache, die Sie möchten haben, though there are things to consider before doing so.

+1

Ihr 'starts_with' Beispiel löscht eine Menge auf. Ich habe jedoch den Buchabschnitt über 'AsRef' und' Borrow' gelesen - immer noch nicht klar. Erlaubt 'AsRef' die Nötigung zu einem' & str', ohne jedoch das 'starts_with' Beispiel zu berücksichtigen? In welchen Fällen sollte ich 'AsRef anstelle von' Deref' implementieren? Sollte ich beides umsetzen? –

+2

'Deref' ist magisch und kann für einen Typ gemacht werden. 'AsRef' ist komplett nicht-magisch und kann für mehrere Typen verwendet werden. Beide zu implementieren ist üblich. –

Verwandte Themen