簡體   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