考虑以下代码:
trait Animal {
fn make_sound(&self) -> String;
}
struct Cat;
impl Animal for Cat {
fn make_sound(&self) -> String {
"meow".to_string()
}
}
struct Dog;
impl Animal for Dog {
fn make_sound(&self) -> String {
"woof".to_string()
}
}
fn main () {
let dog: Dog = Dog;
let cat: Cat = Cat;
let v: Vec<Animal> = Vec::new();
v.push(cat);
v.push(dog);
for animal in v.iter() {
println!("{}", animal.make_sound());
}
}
当我尝试推送 cat
(类型不匹配)时,编译器告诉我 v
是 Animal
的向量
那么,我如何制作一个属于特征的对象向量,并在每个元素上调用相应的特征方法?
最佳答案
Vec<Animal>
是不合法的,但编译器无法告诉您这一点,因为类型不匹配以某种方式隐藏了它。如果我们删除对 push
的调用,编译器给我们以下错误:
<anon>:22:9: 22:40 error: instantiating a type parameter with an incompatible type `Animal`, which does not fulfill `Sized` [E0144]
<anon>:22 let mut v: Vec<Animal> = Vec::new();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这不合法的原因是 Vec<T>
商店很多T
对象在内存中连续。然而,Animal
是特征,特征没有大小(不保证 Cat
和 Dog
具有相同的大小)。
为了解决这个问题,我们需要在 Vec
中存储一些有大小的东西。 .最直接的解决方案是将值包装在 Box
中,即 Vec<Box<Animal>>
. Box<T>
具有固定大小(如果 T
是特征,则为“胖指针”,否则为简单指针)。
这是一个有效的 main
:
fn main() {
let dog: Dog = Dog;
let cat: Cat = Cat;
let mut v: Vec<Box<Animal>> = Vec::new();
v.push(Box::new(cat));
v.push(Box::new(dog));
for animal in v.iter() {
println!("{}", animal.make_sound());
}
}
关于polymorphism - 属于特征的对象的向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47733463/