2015-05-15 6 views
5

Beim Versuch, die Debug Eigenschaft für einen benutzerdefinierten Typ zu implementieren, stolperte ich über die Implementierung für Vec<T>. Ich habe Schwierigkeiten zu verstehen, wie es funktioniert.Die Debug-Implementierung für Vec verstehen <T>

Die Umsetzung geht so:

impl<T: fmt::Debug> fmt::Debug for Vec<T> { 
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 
     fmt::Debug::fmt(&**self, f) 
    } 
} 

Ich verstehe es die fmt Implementierung für eine andere Art nennt. Was ich nicht verstehen kann ist, welcher Typ es ist. Ich habe versucht, es mit der Hilfe von another question herauszufinden, und suche zwischen dem implementations of Debug für etwas, das angemessen aussieht (vielleicht so etwas wie &[T]), aber mit keinem Erfolg.

Was ist die genaue Bedeutung von &**self in diesem Zusammenhang? Welche Implementierung von Debug wird aufgerufen?

Antwort

8

In solchen Fällen finde ich es nützlich, dass der Compiler Ihnen sagt, was der Typ ist. Führen Sie einfach einen Typfehler aus und lassen Sie die Compilerdiagnose dies für Sie tun. Der einfachste Weg ist zu versuchen, Ihren Artikel zu etwas vom Typ () zuweisen:

fn main() { 
    let v = &vec![1,2,3]; 
    let() = v; 
    let() = &**v; 
} 

Die Fehler sind:

<anon>:3:9: 3:11 error: mismatched types: 
expected `&collections::vec::Vec<_>`, 
    found `()` 
(expected &-ptr, 
    found()) [E0308] 
<anon>:3  let() = v; 
       ^~ 
<anon>:4:9: 4:11 error: mismatched types: 
expected `&[_]`, 
    found `()` 
(expected &-ptr, 
    found()) [E0308] 
<anon>:4  let() = &**v; 
       ^~ 

So ist v ein &collections::vec::Vec<_> und &**v ist ein &[_].

Ausführlichere, Vec hat dieses:

impl<T> Deref for Vec<T> { 
    type Target = [T]; 
    // ... 
} 

So dereferenzieren wir einmal von &Vec<T> zu einem Vec<T> zu gehen, dereferenzieren wieder ein [T], zu bekommen und dann einmal verweisen auf eine &[T] zu bekommen.

[T] hat dies:

impl<T> Debug for [T] { 
    fn fmt(&self, ...) ...; 
} 

Wenn jedoch für eine geeignete Methode der Suche aufzurufen, Rust wird das Ziel automatically attempt to dereference. Das bedeutet, dass wir die Methode auf [T] von &[T] finden können.

Als corrected by Francis Gagné, nimmt Debug::fmt&self, so dass er direkt mit einem &[T] Aufruf findet die passende Implementierung. Keine Notwendigkeit für eine automatische Referenzierung oder Dereferenzierung.

+0

Vielen Dank! Ich vermisse nur eine Sache: Ich habe eine Implementierung für '[T]' gefunden, aber nicht für '& [T]', wird letzteres aufgerufen? Warum? – toro2k

+1

@ toro2k Ich habe ein bisschen mehr dazu hinzugefügt. Lass es mich wissen, wenn es hilft! – Shepmaster

+2

Ich glaube nicht, dass es eine automatische Dereferenzierung (oder automatische Referenzierung) gibt, weil 'fmt :: Debug :: fmt()' sich selbst als Referenz nimmt, dh es erwartet ein '& [T]', und das ist es gegeben ein '& [T]'. –

Verwandte Themen