向下倾斜Rust Trait组合

时间:2017-01-27 16:34:50

标签: types polymorphism rust

我有两个结构,DogCat

struct Dog {
    weight: f64
}
struct Cat {
    weight: f64
}

和两个特征MakesSoundHasWeight

trait MakesSound {
    fn make_sound(&self);
}

impl MakesSound for Dog {
    fn make_sound(&self) {
        println!("Bark bark!");
    }
}

impl MakesSound for Cat {
    fn make_sound(&self) {
        println!("Go away.");
    }
}

trait HasWeight {
    fn get_weight(&self) -> f64;
}

impl HasWeight for Dog {
    fn get_weight(&self) -> f64 { self.weight }
}

impl HasWeight for Cat {
    fn get_weight(&self) -> f64 { self.weight }
}

我希望能够将它们存储在异构Vec中,然后再利用它们的特征

trait Animal: MakesSound + HasWeight {}
impl<T: MakesSound + HasWeight> Animal for T {}

fn main() {
    let dog = Dog{ weight: 45.0 };
    let cat = Cat{ weight: 12.0 };
    let animals: Vec<&Animal> = vec![&dog, &cat];
    for animal in animals {
        animal.make_sound();
        println!("{}", animal.get_weight());
        //print_weight(animal as &HasWeight);
    }
}

如何定义类型为

print_weight函数
fn print_weight(x: &HasWeight);

所以我的功能需要尽可能少的信息,但我的Vec会尽可能多地存储信息?

取消注释上述行所得的错误是

error: non-scalar cast: `&Animal` as `&HasWeight`

1 个答案:

答案 0 :(得分:2)

这是一个print_weight函数,它对具有HasWeight特征的类型是通用的。不幸的是,我对Rust缺乏经验,告诉你为什么额外的?Sized特征限制是必要的。

fn print_weight<T: HasWeight + ?Sized>(thing: &T) {
    println!("{}", thing.get_weight());
}

这可以在你的循环中调用而不需要任何强制转换:print_weight(animal)

Playground link