![](/img/trans.png)
[英]Understanding "the trait X cannot be made into an object" for `&mut Box<Self>` parameter
[英]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: Sized
到id()
和new()
。 这两个都是特征函数,因此必须在运行时解决。 解析类型的步骤需要称为“vtable”的东西,它只存在于实际具有大小的类型上。 (这至少是我对问题的理解)Self
替换new
上的通用参数,因为这可能是您真正想要的。add_component
中给self
添加mut
id()
的默认实现以实际强制实现结构来覆盖它&dyn Component
向下转换为get_component
中的实际组件类型。 当然可能有不同的解决方案,我只是选择了那个,因为我不想做任何进一步的研究:) 我没有解决您目前只能从get_component
中获取非可变对象的问题。 这可能是您接下来要处理的事情。
总而言之,这是一个带有“姓名”和“年龄”组件的代码的最小工作示例,只是为了证明您的方法是可行的:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.