如何实现特质

问题描述 投票:0回答:1

我正在尝试实现一个新的特质,叫做 AppendBar 对于 String. 它唯一的功能是 append_bar.

据我了解: self 应该是一个String的实例。

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 `()`

谁能帮我理解一下我的误解?

rust traits
1个回答
3
投票

@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"

Playground

这和@loganfsmyth的答案是一样的)。

借用并克隆

如果你期望 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"

游乐场


7
投票
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 还一个 Stringself.clone().push_str("Bar") 的类型,评价为 (),单位类型. 编译器错误是正确的,因为 push_str 函数的类型是 fn push_str(&mut self, string: &str),注意它没有返回类型,而是突变了它的 Self 参数,而不是推入字符串,然后返回字符串,例如

取而代之的是,你需要推入字符串,然后返回字符串,例如。

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

我还删除了 .clone() 因为没有必要。append_bar 已经接受 self 从而拥有字符串值的所有权,所以你可以推入它并返回它,而不需要克隆它。

© www.soinside.com 2019 - 2024. All rights reserved.