2015-05-15 15 views
5

Cố gắng triển khai đặc điểm Debug cho loại tùy chỉnh mà tôi đã tình cờ triển khai cho Vec<T>. Tôi gặp khó khăn trong việc hiểu cách hoạt động của nó.Hiểu việc triển khai Gỡ lỗi cho Vec <T>

Việc thực hiện đi như thế này:

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

Tôi hiểu nó gọi thi fmt đối với một số loại khác. Những gì tôi không thể hiểu là loại nó là gì. Tôi đã cố gắng để tìm ra nó với sự giúp đỡ của another question, và tìm kiếm trong số implementations of Debug cho một cái gì đó có vẻ thích hợp (có thể một cái gì đó như &[T]), nhưng không thành công.

Ý nghĩa chính xác của &**self trong ngữ cảnh này là gì? Việc triển khai Debug nào đang được thực hiện?

Trả lời

8

Trong trường hợp như thế này, tôi thấy hữu ích khi làm cho trình biên dịch cho bạn biết loại đó là gì. Chỉ gây ra lỗi kiểu và cho phép trình chẩn đoán trình biên dịch làm điều đó cho bạn. Cách đơn giản nhất là cố gắng gán mục của bạn để một cái gì đó kiểu ():

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

Các lỗi là:

<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; 
       ^~ 

Như vậy v là một &collections::vec::Vec<_>&**v là một &[_].

chi tiết hơn, Vec có này:

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

Vì vậy, chúng tôi dereference một lần để đi từ &Vec<T> đến một Vec<T>, dereference lại để có được một [T], và sau đó tham khảo một lần để có được một &[T].

[T] có này:

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

Tuy nhiên, khi tìm kiếm một phương pháp thích hợp để gọi, Rust sẽ automatically attempt to dereference mục tiêu. Điều đó có nghĩa là chúng tôi có thể tìm thấy phương thức trên [T] từ một số &[T].

corrected by Francis Gagné, Debug::fmt mất &self, vì vậy, hãy gọi trực tiếp với số &[T] tìm cách triển khai phù hợp. Không cần cho bất kỳ tham chiếu tự động hoặc dereferencing.

+0

Cảm ơn bạn! Tôi chỉ nhớ một điều: Tôi đã tìm thấy một thực hiện cho '[T]' nhưng không phải cho '& [T]', là nó sau này được gọi? Tại sao? – toro2k

+1

@ toro2k Tôi đã thêm một chút về điều đó. Hãy cho tôi biết nếu nó giúp! – Shepmaster

+2

Tôi không nghĩ rằng có bất kỳ tự động dereferencing (hoặc tự động tham khảo), bởi vì 'fmt :: Debug :: fmt()' mất 'self' bằng cách tham khảo, tức là nó hy vọng một' & [T] ', và nó đưa ra một '& [T]'. –

Các vấn đề liên quan