我正在尝试实现一个新的特质,叫做 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 `()`
谁能帮我理解一下我的误解?
@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"
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
从而拥有字符串值的所有权,所以你可以推入它并返回它,而不需要克隆它。