如何实现特质
How to implement a trait
我正在尝试为 String
实现一个名为 AppendBar
的新特征。它的唯一功能是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 `()`
谁能帮我理解我的误解?
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
到 return 一个 String
,但是 self.clone().push_str("Bar")
求值为 ()
, the unit type. The compiler error is correct, because the push_str
函数的类型是 fn push_str(&mut self, string: &str)
,注意它没有 return 类型,而是改变了它的 Self
参数。
相反,您需要先推入字符串,然后 return 推入字符串,例如
impl AppendBar for String {
fn append_bar(mut self) -> Self{
self.push_str("Bar");
self
}
}
我还删除了 .clone()
,因为没有必要。 append_bar
已经接受 self
并因此获得字符串值的所有权,因此您可以将其推入并 return 它而无需克隆它。
@loganfsmyth 的回答解释了您收到此错误消息的原因。根据您对append_bar
:
的期望,可以通过三种方式解决
取得所有权
如果您希望 append_bar
到 return 修改后的字符串并且不希望调用者之后能够使用输入字符串:
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
到 return 修改后的字符串并希望调用者之后能够继续使用原始输入字符串:
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"
我正在尝试为 String
实现一个名为 AppendBar
的新特征。它的唯一功能是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 `()`
谁能帮我理解我的误解?
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
到 return 一个 String
,但是 self.clone().push_str("Bar")
求值为 ()
, the unit type. The compiler error is correct, because the push_str
函数的类型是 fn push_str(&mut self, string: &str)
,注意它没有 return 类型,而是改变了它的 Self
参数。
相反,您需要先推入字符串,然后 return 推入字符串,例如
impl AppendBar for String {
fn append_bar(mut self) -> Self{
self.push_str("Bar");
self
}
}
我还删除了 .clone()
,因为没有必要。 append_bar
已经接受 self
并因此获得字符串值的所有权,因此您可以将其推入并 return 它而无需克隆它。
@loganfsmyth 的回答解释了您收到此错误消息的原因。根据您对append_bar
:
取得所有权
如果您希望 append_bar
到 return 修改后的字符串并且不希望调用者之后能够使用输入字符串:
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
到 return 修改后的字符串并希望调用者之后能够继续使用原始输入字符串:
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"