2015-09-14 7 views
11

Definiuję API skrzynki w Solid stabilnym (od teraz, wersja 1.2) i jestem zakłopotany o najlepszych praktykach do definiowania własnych typów łańcuchowych.Kiedy używać AsRef lub innych cech konwersji dla typu łańcuchowego

Na przykład mam typ Foo, który otacza ciąg znaków.

pub struct Foo(String); 

Moje API ukrywa konstrukcję z Foo instancji, a ponadto, ponieważ pole krotka jest prywatny, aplikacja nie może błędnie skonstruować nieprawidłowy Foo wartość dla siebie. Oznacza to, że mój interfejs API ogranicza aplikację do pracy tylko z ważnymi wartościami Foo. Jak na razie dobrze.

Jednak chcę, aby aplikacja mogła korzystać z instancji Foo tak, jakby była ciągiem - powiedzmy, wydrukowała go, zalogowała się, zapisała w pliku i przekazała do skrzynki innej firmy, która akceptuje numer &str, konstruowanie kopii za pomocą to_string() i mutowanie kopii itp. Krótko mówiąc, chcę, aby aplikacja mogła "odrzucić" Foo -ness i pracować z referencją do ukrytego ciągu znaków. Ponieważ aplikacja nie może przekonwertować nieprzetworzonego łańcucha z powrotem na instancję Foo, zabezpieczenie typu jest zachowane.

Moje pytanie brzmi: Jakie cechy konwersji, jeśli w ogóle, powinna moja skrzynia implementować dla Foo, aby umożliwić aplikacji "odrzucenie" Foo -ness i pracować z bazowym łańcuchem jako nieprzetworzonym łańcuchem? Ważne jest, aby Foo przekonwertować na &str, aby uniknąć niepotrzebnego kopiowania ciągu podstawowego.

Na przykład, jak o?

impl AsRef<str> for Foo 

Czy to słuszne zadanie? Czy wystarczy być idiomatycznym? Czy są jakieś inne cechy konwersji, które powinienem rozważyć dla wdrożenia Foo?

Odpowiedz

8

Jeśli Foojest semantycznie ciąg, a następnie wdrożenie Deref<Target = str> (ewentualnie Deref<Target = String> i DerefMut) jest najważniejszą rzeczą do zrobienia. To pozwoli &Foo wymusić na &str, aby można było napisać takie rzeczy, jak &*foo, aby uzyskać &str z Foo i foo.starts_with("bar") i takie, metody wywoływania, które są zdefiniowane na str.

Wdrażanie AsRef przyniesie również korzyści niektórym rzeczom. Borrow to kolejna rzecz, którą może chcesz mieć, though there are things to consider before doing so.

+1

Twój przykład 'starts_with' czyści wiele. Jednak przeczytałem sekcję książek o 'AsRef' i' Pożyczce' - wciąż nie jest jasne. Czy 'AsRef' pozwala na wymuszenie na' i str', ale bez zezwolenia na przykład 'starts_with'? Jakie są przypadki, w których powinienem wdrożyć 'AsRef zamiast' Deref'? Czy powinienem wdrożyć oba? –

+2

'Deref' jest magiczne i może być wykonane dla jednego typu. 'AsRef' jest całkowicie nie-magiczne i może być wykonane dla wielu typów. Wdrażanie obu jest powszechne. –

Powiązane problemy