2016-05-22 10 views
9

Załóżmy, że mam kod:Jak poprawnie zaimplementować funkcję ToString dla struktury?

struct A { 
    names: Vec<String>, 
} 

impl ToString for A { 
    fn to_string(&self) -> String { 
     // code here 
    } 
} 

fn main() { 
    let a = A { names: vec![ 
     "Victor".to_string(), 
     "Paul".to_string(), 
    ]}; 
    println!("A struct contains: [{}].", a.to_string()); 
} 

oczekiwany wynik:

struct zawiera: [Victor Paul].

Jakie są najlepsze sposoby wdrożenia tej cechy, aby osiągnąć cel przy maksymalnym wykorzystaniu rdzy?

Próbowałem trochę dziwne 'dla każdego' i inne rzeczy, ale każdy daje mi spływu przecinek tak:

Victor, Paul

Oczywiście mogę to pop później, ale ja jestem zainteresowany językiem, więc chcę poznać najlepszą praktykę tego. To tylko przykład tego, co próbowałem, ale to nie ma znaczenia, pytam, jak zrobić to w sposób najbardziej efektywny i lepszy w rozumieniu języka Rust.

P.S. Uczę się jeszcze Rust.

Odpowiedz

13

Według ToStringdocumentation:

Cecha ta jest realizowana automatycznie dla każdego typu, który implementuje cechę Display. Jako takie, ToString nie powinny być implementowane bezpośrednio: Display powinny być zaimplementowane zamiast, a otrzymasz implementację ToString za darmo.

można zaimplementować Display takiego:

fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 
    let mut str = ""; 
    for name in &self.names { 
     try!(fmt.write_str(str)); 
     try!(fmt.write_str(name)); 
     str = ", "; 
    } 
    Ok(()) 
} 

I nie trzeba zadzwonić to_string (ale można):

fn main() { 
    let a = A { names: vec![ 
     "Victor".to_string(), 
     "Paul".to_string(), 
    ]}; 
    println!("A struct contains: [{}].", a); 
} 

Uwaga celem Display:

Display jest podobny do Debug, ale Display jest przeznaczony dla danych wyjściowych skierowanych do użytkownika i dlatego nie można go wyprowadzić.

Jeśli zamiarem jest debug można czerpać Debug:

#[derive(Debug)] 
struct A { 
    names: Vec<String>, 
} 

fn main() { 
    let a = A { names: vec![ 
     "Victor".to_string(), 
     "Paul".to_string(), 
    ]}; 
    // {:?} is used for debug 
    println!("{:?}", a); 
} 

Wyjścia:

A { names: ["Victor", "Paul"] } 

Formatter struct oferuje bogate zbiory metod, więc można napisać własną Debug implementacja:

impl fmt::Debug for A { 
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 
     fmt.debug_struct("A") 
      .field("names", &self.names) 
      .finish() 
    } 
} 
+0

Wszystko wygląda świetnie, ale czy powinienem dbać o zwracaną wartość 'fmt.write_str()'? Kompilator skarży się, że wynik musi być użyty i daje ostrzeżenie. –

+0

Masz rację. Wywołanie musi być opakowane przez ['try!'] (Https: // doc.rust-lang.org/stable/std/macro.try!.html) makro. Zaktualizowałem odpowiedź. Dzięki. – malbarbo

+0

Co myślisz o zamknięciu jako duplikat http://stackoverflow.com/q/22243527/155423? – Shepmaster

Powiązane problemy