当前位置: 首页 > 知识库问答 >
问题:

如何创建异构对象集合?

颛孙英勋
2023-03-14

我想在 Vec 中使用 trait 对象。在C中,我可以制作一个基类Thing,从中派生出Monster1Monster2。然后我可以创建一个std::vector

目前我有这样的东西

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()方法攻击()make_noise()方法,并为怪物1和怪兽2实现了它们。


共有1个答案

温星华
2023-03-14

实现异构对象集合(在本例中为vector)的最具可扩展性的方式正是您所拥有的:

Vec<Box<dyn ThingTrait + 'static>>

尽管有时您可能希望一生不是'静态,但您需要这样的东西:

Vec<Box<dyn ThingTrait + 'a>>

您还可以有一组对trait的引用,而不是装箱的trait:

Vec<&dyn ThingTrait>

一个例子:

trait ThingTrait {
    fn attack(&self);
}

impl ThingTrait for Monster1 {
    fn attack(&self) {
        println!("monster 1 attacks")
    }
}

impl ThingTrait for Monster2 {
    fn attack(&self) {
        println!("monster 2 attacks")
    }
}

fn main() {
    let m1 = Monster1 {
        thing_record: ThingRecord { x: 42, y: 32 },
        num_arrows: 2,
    };

    let m2 = Monster2 {
        thing_record: ThingRecord { x: 42, y: 32 },
        num_fireballs: 65,
    };

    let things: Vec<Box<dyn ThingTrait>> = vec![Box::new(m1), Box::new(m2)];
}

<代码>框

另请参阅:

    < li >什么使某物成为“特征对象”? < Li > type中的“dyn”是什么意思?

如评论中所述,如果您有固定数量的已知备选方案,则使用枚举是一种不太开放的解决方案。这并不要求将值设置为<code>Box</code>ed,但仍需要少量的动态调度,以确定运行时存在哪个具体的枚举变量:

enum Monster {
    One(Monster1),
    Two(Monster2),
}

impl Monster {
    fn attack(&self) {
        match *self {
            Monster::One(_) => println!("monster 1 attacks"),
            Monster::Two(_) => println!("monster 2 attacks"),
        }
    }
}

fn main() {
    let m1 = Monster1 {
        thing_record: ThingRecord { x: 42, y: 32 },
        num_arrows: 2,
    };

    let m2 = Monster2 {
        thing_record: ThingRecord { x: 42, y: 32 },
        num_fireballs: 65,
    };

    let things = vec![Monster::One(m1), Monster::Two(m2)];
}

另请参阅:

  • 为什么枚举需要额外的内存大小?
 类似资料:
  • 我正在制作Spring云流Kafka流活页夹。在我的consumerbean方法中,我希望返回KStream,并将字符串列表作为值- 是否可以使用集合作为其值的KStream?如果是,有人能解释一下如何创建它吗?

  • 问题内容: 我一直在阅读《Oracle数据库JDBC开发人员指南》和 创建阵列对象 服务器端内部驱动程序 oracle.jdbc.OracleConnection oracle.jdbc.OracleDriver 但是我仍然无法编写一个最低代码,可以在其中创建ARRAY 按照创建ARRAY对象中的指示。 我正在使用Oracle数据库JVM。 我尝试了以下方法: 例子1 失败: 例子2 失败: 免责

  • 问题内容: 如何在Python中创建对象(类实例)列表? 还是这是不良设计的结果?我需要这个原因是因为我有不同的对象,并且需要在以后的阶段中处理它们,所以我将继续将它们添加到列表中,然后再调用它们。 问题答案: 存储对象实例列表非常简单

  • 问题内容: 如何从Swift XCode中的日期创建日期对象。 例如在JavaScript中,你会做: 问题答案: 雨燕有自己的类型。无需使用。 在Swift中,日期和时间存储在64位浮点数中,该浮点数用于测量自2001年1月1日UTC的参考日期以来的秒数。这在结构中表示出来。以下内容将为您提供当前日期和时间: 若要创建其他日期时间,可以使用以下方法之一。 方法一 如果您知道2001年参考日期之前

  • 问题内容: 我在一个项目中使用了一个生成器类。 假设我有一个基于以下类的构建器。 我需要新的构建基于克隆,使包含所有已经存在的价值。 在我的构造函数中,我基于已设置的字段初始化一些字段(未直接设置)。 -我正在初始化这个领域。如果存在,则将设置该值或将设置。 -我也在同一构造函数中初始化此字段。 最重要的是,我在地图上放置了一些必填字段。我不确定这样做的正确方法是什么。不过,我需要补充和成图。(一

  • 问题内容: 我需要从URL对象创建一个File对象我的需求是我需要创建一个网络图像的文件对象(例如googles徽标) 问题答案: 您可以利用以便从URL加载图像,然后将其写入文件。像这样: 如果需要,这还允许您将图像转换为其他格式。