如何创建异构的对象集合?

如何创建异构的对象集合?

我想在一个中使用特征对象Vec。在C ++中我可以使一个基类Thing从中导出Monster1Monster2。然后我可以创建一个std::vector<Thing*>Thing对象必须存储一些数据,例如x : int, y : int,派生类需要添加更多数据。

目前我有类似的东西

struct Level {
    // some stuff here
    pub things: Vec<Box<ThingTrait + 'static>>,}struct ThingRecord {
    x: i32,
    y: i32,}struct Monster1 {
    thing_record: ThingRecord,
    num_arrows: i32,}struct Monster2 {
    thing_record: ThingRecord,
    num_fireballs: i32,}

我定义了一个ThingTrait与方法get_thing_record()attack()make_noise()等,并实现它们的Monster1Monster2


ibeautiful
浏览 451回答 1
1回答

千巷猫影

特质对象实现对象的异构集合(在本例中为向量)的最可扩展方式正是您所拥有的:Vec<Box<dyn&nbsp;ThingTrait&nbsp;+&nbsp;'static>>虽然有些时候你可能想要一辈子没有'static,所以你需要这样的东西:Vec<Box<dyn&nbsp;ThingTrait&nbsp;+&nbsp;'a>>您还可以拥有对特征的引用集合,而不是盒装特征:Vec<&dyn&nbsp;ThingTrait>一个例子:trait&nbsp;ThingTrait&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;attack(&self);}impl&nbsp;ThingTrait&nbsp;for&nbsp;Monster1&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;attack(&self)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;println!("monster&nbsp;1&nbsp;attacks") &nbsp;&nbsp;&nbsp;&nbsp;}}impl&nbsp;ThingTrait&nbsp;for&nbsp;Monster2&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;attack(&self)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;println!("monster&nbsp;2&nbsp;attacks") &nbsp;&nbsp;&nbsp;&nbsp;}}fn&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;m1&nbsp;=&nbsp;Monster1&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thing_record:&nbsp;ThingRecord&nbsp;{&nbsp;x:&nbsp;42,&nbsp;y:&nbsp;32&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num_arrows:&nbsp;2, &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;m2&nbsp;=&nbsp;Monster2&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thing_record:&nbsp;ThingRecord&nbsp;{&nbsp;x:&nbsp;42,&nbsp;y:&nbsp;32&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num_fireballs:&nbsp;65, &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;things:&nbsp;Vec<Box<dyn&nbsp;ThingTrait>>&nbsp;=&nbsp;vec![Box::new(m1),&nbsp;Box::new(m2)];}Box<SomeTrait>,Rc<SomeTrait>,&SomeTrait等都是性状的对象。这些允许在无数种类型上实现特征,但权衡是需要一定量的间接和动态调度。枚举正如评论中所提到的,如果您有固定数量的已知替代方案,那么开放性较低的解决方案就是使用枚举。这不需要Box编辑值,但它仍然会有少量的动态调度来决定运行时存在哪个具体的枚举变量:enum&nbsp;Monster&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;One(Monster1), &nbsp;&nbsp;&nbsp;&nbsp;Two(Monster2),}impl&nbsp;Monster&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;attack(&self)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;match&nbsp;*self&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Monster::One(_)&nbsp;=>&nbsp;println!("monster&nbsp;1&nbsp;attacks"), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Monster::Two(_)&nbsp;=>&nbsp;println!("monster&nbsp;2&nbsp;attacks"), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}}fn&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;m1&nbsp;=&nbsp;Monster1&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thing_record:&nbsp;ThingRecord&nbsp;{&nbsp;x:&nbsp;42,&nbsp;y:&nbsp;32&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num_arrows:&nbsp;2, &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;m2&nbsp;=&nbsp;Monster2&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thing_record:&nbsp;ThingRecord&nbsp;{&nbsp;x:&nbsp;42,&nbsp;y:&nbsp;32&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num_fireballs:&nbsp;65, &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;things&nbsp;=&nbsp;vec![Monster::One(m1),&nbsp;Monster::Two(m2)];}
打开App,查看更多内容
随时随地看视频慕课网APP