Как реализовать черту - PullRequest
0 голосов
/ 23 апреля 2020

Я пытаюсь реализовать новую черту AppendBar для String. Его единственная функция - append_bar.

Насколько я понимаю, self должен быть экземпляром строки.

trait AppendBar {
    fn append_bar(self) -> Self;
}

impl AppendBar for String {
    fn append_bar(self) -> Self{
        self.clone().push_str("Bar")
    }
}

fn main() {
    let s = String::from("Foo");
    let s = s.append_bar();
    println!("s: {}", s);  // "s: FooBar"
}

Это, очевидно, не тот случай, потому что я получаю следующее ошибка:

error[E0308]: mismatched types
  --> exercises/traits/traits1.rs:18:9
   |
17 |     fn append_bar(self) -> Self{
   |                            ---- expected `std::string::String` because of return type
18 |         self.clone().push_str("Bar")
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found `()`

Может кто-нибудь помочь мне понять мое заблуждение?

Ответы [ 2 ]

7 голосов
/ 23 апреля 2020
17 |     fn append_bar(self) -> Self{
   |                            ---- expected `std::string::String` because of return type
18 |         self.clone().push_str("Bar")
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found `()`

говорит, что ожидал, что append_bar вернет String, но self.clone().push_str("Bar") оценивает тип (), тип единицы . Ошибка компилятора верна, поскольку тип функции push_str равен fn push_str(&mut self, string: &str), обратите внимание, что она не имеет возвращаемого типа и вместо этого изменяет свой аргумент Self.

Вместо этого вам нужно вставить в строку строку sh, а затем вернуть строку, например,

impl AppendBar for String {
    fn append_bar(mut self) -> Self{
        self.push_str("Bar");
        self
    }
}

Я также удалил .clone(), поскольку в этом не было необходимости. append_bar уже принимает self и, таким образом, становится владельцем строкового значения, так что вы можете вставить в него sh и вернуть его без необходимости клонировать его.

2 голосов
/ 23 апреля 2020

@ ответ loganfsmyth объясняет, почему вы получаете это сообщение об ошибке. Есть три способа решить эту проблему в зависимости от ваших ожиданий для append_bar:

Стать владельцем

Если вы ожидаете, что append_bar вернет измененную строку и не хочет, чтобы вызывающая сторона была впоследствии можно использовать входную строку:

impl AppendBar for String {
    fn append_bar (mut self) -> Self {
        self.push_str ("Bar");
        self
    }
}
let s1 = String::from ("Foo");
let s2 = s1.append_bar();
// println!("s1: {}", s1);    // Error: s1 is no longer usable at this point
println!("s2: {}", s2);    // Prints "FooBar"

Детская площадка

(Это то же решение, что и ответ @ loganfsmyth).

Взять и clone

Если вы ожидаете, что append_bar вернет измененную строку и хотите, чтобы вызывающая сторона могла впоследствии использовать исходную строку ввода:

impl AppendBar for String {
    fn append_bar (&self) -> Self {
        let mut s = self.clone();
        s.push_str ("Bar");
        s
    }
}
let s1 = String::from ("Foo");
let s2 = s1.append_bar();
println!("s1: {}", s1);    // Prints "Foo"
println!("s2: {}", s2);    // Prints "FooBar"

Playground

Мутировать на месте

Если вы ожидаете, что append_bar заменит ввод измененной строкой:

impl AppendBar for String {
    fn append_bar (&mut self) {
        self.push_str ("Bar");
    }
}
let mut s1 = String::from ("Foo");
s1.append_bar();
println!("s1: {}", s1);    // Prints "FooBar"

Детская площадка

...