[英]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.