![](/img/trans.png)
[英]Rustlings traits4.rs Why impl Trait syntax works but trait bound syntax or where clause does not work
[英]Rustlings Exercise Traits2, Implement Trait on Vec
该练习要求我将特征实现到 Vec。 测试就在那里,但它们都失败了,这是一个很好的起点。 我已经完成了 String 的 trait 实现,这很简单,Vec 是另一回事。 我不确定该方法需要返回什么,它在各种返回时都失败了。 我正在提供原始代码、我的尝试以及我尝试时遇到的错误。 希望这就足够了。
Rustlings 仓库的原始代码:
// traits2.rs
//
// Your task is to implement the trait
// `AppendBar' for a vector of strings.
//
// To implement this trait, consider for
// a moment what it means to 'append "Bar"'
// to a vector of strings.
//
// No boiler plate code this time,
// you can do this!
// I AM NOT DONE
trait AppendBar {
fn append_bar(self) -> Self;
}
//TODO: Add your code here
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_vec_pop_eq_bar() {
let mut foo = vec![String::from("Foo")].append_bar();
assert_eq!(foo.pop().unwrap(), String::from("Bar"));
assert_eq!(foo.pop().unwrap(), String::from("Foo"));
}
}
我试图解决它:
// traits2.rs
//
// Your task is to implement the trait
// `AppendBar' for a vector of strings.
//
// To implement this trait, consider for
// a moment what it means to 'append "Bar"'
// to a vector of strings.
//
// No boiler plate code this time,
// you can do this!
// I AM NOT DONE
use std::clone::Clone;
trait AppendBar {
fn append_bar(&mut self) -> Self;
}
//TODO: Add your code here
impl<T: Clone> AppendBar for Vec<T> {
fn append_bar(&mut self) -> Self {
let bar: T = String::from("Bar");
self.to_vec().push(bar)
// self.to_vec()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_vec_pop_eq_bar() {
let mut foo = vec![String::from("Foo")].append_bar();
assert_eq!(foo, vec![String::from("Foo"), String::from("Bar")]);
assert_eq!(foo.pop().unwrap(), String::from("Bar"));
assert_eq!(foo.pop().unwrap(), String::from("Foo"));
}
}
编译为错误:
! Compiling of exercises/traits/traits2.rs failed! Please try again. Here's the output:
error[E0308]: mismatched types
--> exercises/traits/traits2.rs:22:22
|
20 | impl<T: Clone> AppendBar for Vec<T> {
| - this type parameter
21 | fn append_bar(&mut self) -> Self {
22 | let bar: T = String::from("Bar");
| - ^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found struct `std::string::String`
| |
| expected due to this
|
= note: expected type parameter `T`
found struct `std::string::String`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
error[E0308]: mismatched types
--> exercises/traits/traits2.rs:23:9
|
21 | fn append_bar(&mut self) -> Self {
| ---- expected `std::vec::Vec<T>` because of return type
22 | let bar: T = String::from("Bar");
23 | self.to_vec().push(bar)
| ^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found `()`
|
= note: expected struct `std::vec::Vec<T>`
found unit type `()`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.
我已经阅读并重新阅读了书中建议的部分和特征,但它超出了我的范围。 我确定这是一个简单的解决方案,但我看不到它。
Aloso 的回答有出入。 安德烈也给了。
当你接受self
:
fn append_bar(self) -> Self {
self.push("Bar".to_owned());
self
}
你正在接受一个可变的Vec
:
let mut foo = vec![String::from("Foo")].append_bar();
assert_eq!(foo.pop().unwrap(), String::from("Bar"));
assert_eq!(foo.pop().unwrap(), String::from("Foo"));
即使变量foo
被声明为可变的,方法append_bar()
接受一个不可变的变量。 您不需要借用self
因为您不是试图获得全部所有权,而是试图修改驻留在所述变量中的现有数据。 正确答案是
fn append_bar(mut self) -> Self {
self.push("Bar".to_owned()); // || .to_string() || String::from("Bar")
// Whatever gets the point across. As the String literal is essentially a "Borrowed" string.
self
}
在append_bar()
的范围内,您试图改变String
的集合并将其与附加的字符串一起返回。
有几个问题:
String
推送到泛型Vec<T>
,其中T
可以是任何类型!fn append_bar(&mut self) -> Self
但应该是fn append_bar(self) -> Self
Vec::push
的结果,但此方法不返回任何内容。 要解决第一个问题,请为Vec<String>
而不是Vec<T>
。 这就是作业要求的内容:
// Your task is to implement the trait // `AppendBar' for a vector of strings.
要解决第二个问题,您必须删除&
,因此该方法接受一个拥有的值。
要解决最后一个问题,请在单独的语句中调用Vec::push
后返回self
:
self.push(bar);
self
感谢@Aloso 和 Jussi 的帮助,我设法使示例正常工作。
为了编译需要突变,所以我最终得到了编译如下的代码:
// traits2.rs
//
// Your task is to implement the trait
// `AppendBar' for a vector of strings.
//
// To implement this trait, consider for
// a moment what it means to 'append "Bar"'
// to a vector of strings.
//
// No boiler plate code this time,
// you can do this!
// I AM NOT DONE
trait AppendBar {
fn append_bar(&mut self) -> Self;
}
//TODO: Add your code here
impl AppendBar for Vec<String> {
fn append_bar(&mut self) -> Self {
self.push(String::from("Bar"));
self.to_vec()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_vec_pop_eq_bar() {
let mut foo = vec![String::from("Foo")].append_bar();
assert_eq!(foo, vec![String::from("Foo"), String::from("Bar")]);
assert_eq!(foo.pop().unwrap(), String::from("Bar"));
assert_eq!(foo.pop().unwrap(), String::from("Foo"));
}
}
我相信这个问题的正确答案应该是这样的:
trait AppendBar {
fn append_bar(self) -> Self;
}
impl AppendBar for Vec<String> {
fn append_bar(mut self) -> Self {
self.push("Bar".to_string());
self
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.