2015-04-15 9 views
5

Poniższe ilustracje pokazują, z jakiego źródła pochodzi. Ponieważ as_slice() jest przestarzałe, sugeruje się zastąpienie as_ref().Jak zapewnić adnotację typu dla `AsRef`?

Jednak w przypadku korzystania z niego w tym kontekście wymagana jest adnotacja typu.

let s = "Hi";    // This is a string slice 
// warning: use of deprecated item: use std::convert::AsRef<str> instead, #[warn(deprecated)] on by default 
assert!(s.replace("Hi", "Ho").as_slice() == "Ho"); 
// tests/lang.rs:120:35: 120:43 error: type annotations required: cannot resolve `collections::string::String : core::convert::AsRef<_>` [E0283] 
// assert!(s.replace("Hi", "Ho").as_ref() == "Ho"); 

Jak mogę podać taką adnotację typu?. Jedyną składnią, którą mogę znaleźć w pewnym sensie jest <MyType as AsRef>::as_ref(), ale nie wiem jak to zrobić z instancją.

Używam rustc 1.0.0-nightly (be9bd7c93 2015-04-05) (built 2015-04-05).

+0

Przy okazji: ten przykład jest oparty na starym teście, który został przeniesiony do najnowszego rustc. W dawnych czasach as_slice() było nadal potrzebne. W dzisiejszych czasach można polegać tylko na automatycznych konwersjach opisanych w różnych odpowiedziach. – Byron

Odpowiedz

6

W swojej precyzyjnej przypadku String i &str, najprostszym jest użycie składni Index:

let s: String = "foo".to_string(); 
let slice: &str = &s[..]; // full range index 

co w Twoim przypadku, to podać:

let s = "Hi"; 
assert!(&s.replace("Hi", "Ho")[..] == "Ho"); 

Jednak dla cech metod, takich jak as_ref(), można również wywoływać je za pomocą składni:

Trait::method(obj); // equivalent to obj.method(); 

które pozwalają na ustawienie parametrów typów tak:

Trait::<T>::method(obj); 

w Twoim przypadku, składnia alternatywna byłoby zatem:

let s = "Hi"; 
assert!(AsRef::<str>::as_ref(&s.replace("Hi", "Ho")) == "Ho"); 
+0

W rzeczywistości '& s' (to jest bez krojenia) jest jeszcze prostsze. – delnan

+0

@delnan Tak, rzeczywiście, nie zadzwoniłem. Ale to nie zawsze działa (jeśli chcesz "dopasować" 'String' do zestawu wartości' i str' dla przykładów, takich jak ten http://is.gd/VDuUjn) – Levans

+0

Tak, to musi być w kontekst, w którym mają zastosowanie ograniczenia dotyczące derefa. Chociaż zawsze można zrobić 'let foo_str: & str = &foo;' i użyć tego. – delnan

8

W tym konkretnym przypadku, nie trzeba żadnych fanciness w ogóle: String jest porównywalna z &str (jest realizacja PartialEq<&str> na String), więc można tylko porównać je bezpośrednio:

let s = "Hi"; 
assert!(s.replace("Hi", "Ho") == "Ho"); 
// Or, if you prefer: 
assert_eq!(s.replace("Hi", "Ho"), "Ho"); 

W prawdziwym życiu często nie trzeba dzwonić pod numer as_ref z takich powodów.

+2

To nie jest 'Deref' impl/dereferencing, to jest' impl <'a> PartialEq <&'a str> dla String': http://doc.rust-lang.org/std/string/struct.String.html – huon

+0

@ huon-dbaupp : Słuszna uwaga. Nie przestawałem myśleć o tym poprawnie, ale rzeczy takie jak '==' nie robią żadnego autoref/autoderef w ten sposób. –

Powiązane problemy