簡體   English   中英

Rust Trait對象轉換

[英]Rust Trait object conversion

由於此錯誤的兩個實例,以下代碼將無法編譯:

錯誤[E0277]:特征綁定Self: std::marker::Sized不滿足

我不明白為什么在這個實例中需要Sized因為&self&Any都是指針而且操作不需要知道實現特征的結構的大小,它只需要知道指針本身及其類型。轉換和轉換,因為&self在特征中實現時是通用的。

我認為這可能是編譯器強制執行不必要的約束的一個實例,我考慮過使用生銹的GitHub倉庫提出問題,但我想我應該看看,在我提出問題之前,有人在這里知道我不知道的事情。

use std::any::Any;

trait Component: Any {
    fn as_any(&self) -> &Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut Any {
        self
    }
}

替代方法是為實現此特征的結構使as_any()as_any_mut()必需的函數,但對於這些結構,實現將始終完全按照此處顯示到每個單獨的字符,從而生成相同樣板的多個實例碼。

動態大小的類型也可以實現特征。 特別是,當您定義對象安全特征時,編譯器還會定義一個動態大小的類型,其名稱與特征相同,這使您可以使用對象類型,如&Component

諸如&Component&Any類的對象類型不僅僅是普通的指針; 他們是胖子 胖指針結合了指向數據的指針和另一個數據:對於對象類型,它是指向vtable的指針; 對於切片,它是切片的長度。

當從常規指針(例如&Button )轉換為對象類型時,編譯器靜態地知道將哪個vtable放入胖指針(例如Button的vtable for Any )。 另一方面,Rust不支持從對象類型轉換為另一個對象類型(例如,從&Component&Any ),因為對象中沒有足夠的數據來初始化新的胖指針。 這就是編譯器將此注釋添加到錯誤消息的原因:

= note: required for the cast to the object type `std::any::Any + 'static`

有兩種方法可以解決這個問題:

  1. 要求實現Component所有類型都要調整Sized

     trait Component: Any + Sized { fn as_any(&self) -> &Any { self } fn as_any_mut(&mut self) -> &mut Any { self } } 

    這導致您將無法使用對象類型,例如&ComponentBox<Component>

  2. 使as_anyas_any_mut方法僅在Self Sized時可用:

     trait Component: Any { fn as_any(&self) -> &Any where Self: Sized { self } fn as_any_mut(&mut self) -> &mut Any where Self: Sized { self } } 

    這樣,您仍然可以使用特征的對象類型,但是您無法在它們上調用as_anyas_any_mut

我發現我認為是一個不需要新編譯器功能的優秀解決方案。

pub trait Component {
    // ...
}

pub trait ComponentAny: Component + Any {
    fn as_any(&self) -> &Any;
    fn as_any_mut(&mut self) -> &mut Any;
}

impl<T> ComponentAny for T
    where T: Component + Any
{
    fn as_any(&self) -> &Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut Any {
        self
    }
}

從這里開始,我只需更改所有API以接受ComponentAny而不是Component 因為Any自動對任何實施'static類型, ComponentAny現在自動為任何實現'static實現類型Component 感謝有沒有辦法結合多個特征來定義新的特征? 為了這個想法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM