繁体   English   中英

如何实现一个特征

[英]How to implement a trait

我正在尝试为String实现一个名为AppendBar的新特征。 它唯一的 function 是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 `()`

谁能帮我理解我的误解?

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参数。

相反,您需要推入字符串然后返回字符串,例如

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

我也删除了.clone()因为它不是必需的。 append_bar已经接受了self并因此获得了字符串值的所有权,因此您可以将其推入并返回它,而无需克隆它。

@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 的答案相同)。

借用和克隆

如果您希望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"

操场

原地变异

如果您希望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"

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM