polymorphism - 属于特征的对象的向量

标签 polymorphism rust

考虑以下代码:

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(类型不匹配)时,编译器告诉我 vAnimal 的向量

那么,我如何制作一个属于特征的对象向量,并在每个元素上调用相应的特征方法?

最佳答案

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是特征,特征没有大小(不保证 CatDog 具有相同的大小)。

为了解决这个问题,我们需要在 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/

相关文章:

c++ - 有没有办法关闭 C++ 和 Rust 编译的循环优化?

docker - 在 Docker : Empty reply from server 上运行 rust

c# - 如何调用base.base.method()?

winapi - Rust 中的 Win32 OpenGL 窗口 : unable to load certain function pointers

rust - 有没有办法告诉 Cargo 在主线程上运行它的测试?

rust - 非穷举匹配 i32 即使它是

java - 将父对象转换为子对象 - 数组中的奇怪行为

haskell - 使用 RankNTypes 编码的 System-F 自然数的 "case"运算符无法进行类型检查

java - 在 java 中,我们可以将父类(super class)对象传递给子类引用吗?

c++ - 内存泄漏和多态性