属于特征的对象的向量

考虑以下代码:


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());

    }

}

编译器告诉我这v是Animal我尝试推送cat(类型不匹配)时的向量


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


慕的地6264312
浏览 503回答 2
2回答

呼唤远方

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&nbsp; &nbsp; &nbsp;let mut v: Vec<Animal> = Vec::new();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~之所以不合法,是因为a 在内存中连续Vec<T>存储了许多T对象。但是,Animal是一个特征,特征没有大小(不能保证a Cat和a Dog具有相同的大小)。要解决此问题,我们需要在中存储大小为一定的内容Vec。最直接的解决方案是将这些值包装在Box,即中Vec<Box<Animal>>。Box<T>具有固定大小(如果T是特征,则为“胖指针”,否则为简单指针)。这是一个工作main:fn main () {&nbsp; &nbsp; let dog: Dog = Dog;&nbsp; &nbsp; let cat: Cat = Cat;&nbsp; &nbsp; let mut v: Vec<Box<Animal>> = Vec::new();&nbsp; &nbsp; v.push(Box::new(cat));&nbsp; &nbsp; v.push(Box::new(dog));&nbsp; &nbsp; for animal in v.iter() {&nbsp; &nbsp; &nbsp; &nbsp; println!("{}", animal.make_sound());&nbsp; &nbsp; }}

当年话下

您可以使用参考特征对象&Animal借用元素并将这些特征对象存储在中Vec。然后,您可以枚举它并使用特征的界面。Vec通过&在trait前面添加a 来更改的通用类型将起作用:fn main() {&nbsp; &nbsp; let dog: Dog = Dog;&nbsp; &nbsp; let cat: Cat = Cat;&nbsp; &nbsp; let mut v: Vec<&Animal> = Vec::new();&nbsp; &nbsp; //&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;~~~~~~~&nbsp; &nbsp; v.push(&dog);&nbsp; &nbsp; v.push(&cat);&nbsp; &nbsp; for animal in v.iter() {&nbsp; &nbsp; &nbsp; &nbsp; println!("{}", animal.make_sound());&nbsp; &nbsp; }&nbsp; &nbsp; // Ownership is still bound to the original variable.&nbsp; &nbsp; println!("{}", cat.make_sound());}如果您可能希望原始变量保留所有权并在以后重新使用,那就太好了。请牢记上述情况,您不能转让的所有权,dog或者cat因为Vec曾在相同范围借用了这些具体实例。引入新的作用域可以帮助处理特定情况:fn main() {&nbsp; &nbsp; let dog: Dog = Dog;&nbsp; &nbsp; let cat: Cat = Cat;&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; let mut v: Vec<&Animal> = Vec::new();&nbsp; &nbsp; &nbsp; &nbsp; v.push(&dog);&nbsp; &nbsp; &nbsp; &nbsp; v.push(&cat);&nbsp; &nbsp; &nbsp; &nbsp; for animal in v.iter() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; println!("{}", animal.make_sound());&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; let pete_dog: Dog = dog;&nbsp; &nbsp; println!("{}", pete_dog.make_sound());}
打开App,查看更多内容
随时随地看视频慕课网APP