Types 下铸锈性状组合

Types 下铸锈性状组合,types,polymorphism,rust,Types,Polymorphism,Rust,我有两个结构,Dog和Cat: struct Dog { weight: f64 } struct Cat { weight: f64 } 还有两个特征MakesSound和hasweeght trait MakesSound { fn make_sound(&self); } impl MakesSound for Dog { fn make_sound(&self) { println!("Bark bark!");

我有两个结构,
Dog
Cat

struct Dog {
    weight: f64
}
struct Cat {
    weight: f64
}
还有两个特征
MakesSound
hasweeght

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);
    }
}
所以我的函数需要尽可能少的信息,但是我的
Vec
存储的信息尽可能多

我从取消注释上面这行中得到的错误是

错误:非标量转换:`&Animal`as`&hasweet`

这里有一个
打印权重
函数,它是具有
haswweight
特征的类型的通用函数。不幸的是,我对生锈太缺乏经验,无法告诉您为什么需要额外的
?大小的
特征绑定

fn print_weight<T: HasWeight + ?Sized>(thing: &T) {
    println!("{}", thing.get_weight());
}
fn打印重量(物品:&T){
println!(“{}”,thing.get_weight());
}
这可以在循环中调用,而无需任何施法:
print\u weight(animal)


这里有一个
print\u weight
函数,它是具有
haswweight
特征的类型的通用函数。不幸的是,我对生锈太缺乏经验,无法告诉您为什么需要额外的
?大小的
特征绑定

fn print_weight<T: HasWeight + ?Sized>(thing: &T) {
    println!("{}", thing.get_weight());
}
fn打印重量(物品:&T){
println!(“{}”,thing.get_weight());
}
这可以在循环中调用,而无需任何施法:
print\u weight(animal)


这确实有效,尽管。。。我认为大小特性是一个要求,编译器可以通过告诉它大小是可选的来关闭,这表明编译器可以不使用它。我很想知道静态分派是如何发生的,以及是否仍在发生。为了解决这两个问题:
?大小的
绑定是将T映射到未大小的类型所必需的。特别是,当
T=haswweight
时,函数参数成为一个trait对象(
&haswweight
),它是动态调度的。在其他情况下,参数背后的具体对象类型是已知的,这个类型将被静态调度。。。我认为大小特性是一个要求,编译器可以通过告诉它大小是可选的来关闭,这表明编译器可以不使用它。我很想知道静态分派是如何发生的,以及是否仍在发生。为了解决这两个问题:
?大小的
绑定是将T映射到未大小的类型所必需的。特别是,当
T=haswweight
时,函数参数成为一个trait对象(
&haswweight
),它是动态调度的。对于其他情况,参数背后的具体对象类型是已知的,并且此类型将被静态调度。