[英]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`
有兩種方法可以解決這個問題:
要求實現Component
所有類型都要調整Sized
:
trait Component: Any + Sized { fn as_any(&self) -> &Any { self } fn as_any_mut(&mut self) -> &mut Any { self } }
這導致您將無法使用對象類型,例如&Component
或Box<Component>
。
使as_any
和as_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_any
和as_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.