繁体   English   中英

具有 function 且没有“self”作为参数的特征无法制成 object

[英]Trait with function without "self" as parameter cannot be made into an object

我正在尝试构建一个实体组件系统,作为我学习 Rust 之旅的一部分。我有一个想法,每个组件都有一个 static id,对象将有一个 HashMap 它包含的组件(每个组件限制为一个类型)。

这是 object 本身:

pub struct Object {
    // TODO : components !
    components: HashMap<i32, Box<dyn Component>>
}

impl Object {
    pub fn add_component<C: Component>(&self) {
        self.components.insert(C::id(), Box::new(C::new()));
    }

    pub fn get_component<C: Component>(&self) -> Option<&C> {
        return self.components.get(C::id())
    }
}

这是我的组件特征:

pub trait Component {
    fn id() -> i32 {
        // one must ensure this returns different id for every component
        return 0;
    }

    fn new<C: Component>() -> C;

    fn require_rendering(&self) -> bool {
        return false;
    }

    fn some_function_on_component(&mut self) {
        // do something on the component 
    }
}

不幸的是,我得到这个错误:“这个特征不能变成 object... ...因为关联的 function id没有self参数”

谁能解释为什么这不起作用,以及如何解决它?

通过遵循编译器消息,其中大部分都可以很容易地修复。

我在尝试编译您的代码时遇到的最大障碍是Box<dyn>向下转换回其原始类型

那是我的尝试,我不知道它最终是否真的做了什么,但至少它编译了:)

use std::any::Any;
use std::collections::HashMap;

pub struct Object {
    // TODO : components !
    components: HashMap<i32, Box<dyn Component>>,
}

impl Object {
    pub fn new() -> Self {
        Self {
            components: HashMap::new(),
        }
    }

    pub fn add_component<C: 'static + Component>(&mut self) {
        self.components.insert(C::id(), Box::new(C::new()));
    }

    pub fn get_component<C: 'static + Component>(&self) -> Option<&C> {
        self.components
            .get(&C::id())
            .map(|boxed_component| boxed_component.as_any().downcast_ref::<C>().unwrap())
    }
}

pub trait Component {
    fn id() -> i32
    where
        Self: Sized;

    fn new() -> Self
    where
        Self: Sized;

    fn require_rendering(&self) -> bool {
        return false;
    }

    fn some_function_on_component(&mut self) {
        // do something on the component
    }

    fn as_any(&self) -> &dyn Any;
}

我做过的事情:

  • 添加Self: Sizedid()new() 这两个都是特征函数,因此必须在运行时解决。 解析类型的步骤需要称为“vtable”的东西,它只存在于实际具有大小的类型上。 (这至少是我对问题的理解)
  • Self替换new上的通用参数,因为这可能是您真正想要的。
  • add_component中给self添加mut
  • 删除id()的默认实现以实际强制实现结构来覆盖它
  • 根据这篇文章,将&dyn Component向下转换为get_component中的实际组件类型。 当然可能有不同的解决方案,我只是选择了那个,因为我不想做任何进一步的研究:)

我没有解决您目前只能从get_component中获取非可变对象的问题。 这可能是您接下来要处理的事情。

总而言之,这是一个带有“姓名”和“年龄”组件的代码的最小工作示例,只是为了证明您的方法是可行的:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5d22b64ab924394606a07a043594f608

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM