最初我使用本教程作为一些练习代码的参考。 经过几个小时的故障排除后,我只是简单地按原样尝试了该页面上的代码。
https://doc.rust-lang.org/book/ch17-02-trait-objects.html
pub fn add(left: usize, right: usize) -> usize {
left + right
}
pub trait Draw {
fn draw(&self);
}
pub struct Button {
pub width: u32,
pub height: u32,
pub label: String,
}
impl Draw for Button {
fn draw(&self) {
// code to actually draw a button
}
}
pub struct Screen<T: Draw> {
pub components: Vec<T>,
}
impl<T> Screen<T>
where
T: Draw,
{
pub fn run(&self) {
for component in self.components.iter() {
component.draw();
}
}
}
struct SelectBox {
width: u32,
height: u32,
options: Vec<String>,
}
impl Draw for SelectBox {
fn draw(&self) {
// code to actually draw a select box
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
#[test]
fn test_tell_me(){
let screen = Screen {
components: vec![
Box::new(SelectBox {
width: 75,
height: 10,
options: vec![
String::from("Yes"),
String::from("Maybe"),
String::from("No"),
],
}),
Box::new(Button {
width: 50,
height: 10,
label: String::from("OK"),
}),
],
};
screen.run();
}
}
错误:
warning: `decision-command-parser` (lib) generated 1 warning
error[E0277]: the trait bound `Box<SelectBox>: Draw` is not satisfied
--> src/lib.rs:60:25
|
60 | components: vec![
| _________________________^
61 | | Box::new(SelectBox {
62 | | width: 75,
63 | | height: 10,
... |
74 | | }),
75 | | ],
| |_____________^ the trait `Draw` is not implemented for `Box<SelectBox>`
|
= help: the following other types implement trait `Draw`:
Button
SelectBox
bard.google.com 说我需要将特征添加到按钮,但鉴于它是“书”等,教程应该是事实来源。
书上讲得很清楚了,我觉得:
pub struct Screen { pub components: Vec<Box<dyn Draw>>, }
在
结构体上,我们将定义一个名为Screen
的方法,它将 在每个run
上调用draw
方法,如下所示 示例 17-5:components
impl Screen { pub fn run(&self) { for component in self.components.iter() { component.draw(); } } }
这与定义使用泛型类型的结构不同 具有特征边界的参数。泛型类型参数只能是 一次替换为一种具体类型,而特质对象 允许使用多种具体类型填充特征对象 运行。例如,我们可以使用 a 来定义 Screen 结构体 泛型类型和特征绑定如清单 17-6 所示:
pub struct Screen<T: Draw> { pub components: Vec<T>, } impl<T> Screen<T> where T: Draw, { pub fn run(&self) { for component in self.components.iter() { component.draw(); } } }
这将我们限制为具有组件列表的
实例 全部为Screen
类型或全部为Button
类型。如果你永远 具有同构集合,使用泛型和特征边界是 更可取,因为定义将在编译时单态化 是时候使用具体类型了。TextField
另一方面,使用特征对象的方法,一个
实例可以保存一个包含Screen
的Vec<T>
以及 一个Box<Button>
。让我们看看它是如何工作的,然后我们再讨论 关于运行时性能的影响。Box<TextField>
因此,通用方法可用于同构集合,而特征对象方法可用于异构集合。您尝试使用具有多种类型的通用方法,但正如书中所说,它无法做到这一点。