[英]How to use sized traits in structs?
我正在嘗試使用 AES crate,它提供三種算法:AES128、AES192 和 AES256。 我正在嘗試創建一個結構,該結構可以通過檢測密鑰大小來創建正確的算法,並將其保存以備后用。
我看到它們都實現了 BlockEncrypt(我只需要加密)特性,但是當我嘗試使用這種類型在結構中創建一個字段時,即使提供了大小,我也得到了一個“特性BlockEncrypt
無法制作成 object。該特征不能變成 object 因為它需要Self: Sized
" 錯誤。
pub struct MyStruct<'a, T: Sized> {
ciph: Box< dyn BlockEncrypt<BlockSize = T>>,
}
將Sized
作為超類型的特征不是“對象安全”的,這意味着使用dyn
的動態調度在這些類型的特征上是不可能的。
您可以通過為您想要處理的每種可能類型使用一個枚舉,並結合一個宏,該宏將巧妙地生成動態調度每個枚舉可能性所需的所有match
臂,從而相對簡潔地完成此操作。
為了便於解釋,為了讓事情變得簡單,我將定義一個新特征(使用Sized
超類型),以便這個答案不依賴於特定的板條箱:
trait SampleTrait: Sized {
fn method_a(&self, foo: &str);
fn method_b(&self, foo: i32, bar: String) -> String;
}
現在我們至少需要這個特征的兩個實現來演示解決方案:
struct ImplA;
struct ImplB;
impl SampleTrait for ImplA {
fn method_a(&self, foo: &str) {
println!("<ImplA as SampleTrait>::method_a(): {:?}", foo);
}
fn method_b(&self, foo: i32, bar: String) -> String {
println!("<ImplA as SampleTrait>::method_b(): {:?} {:?}", foo, bar);
format!("from ImplA: {}", bar)
}
}
impl SampleTrait for ImplB {
fn method_a(&self, foo: &str) {
println!("<ImplB as SampleTrait>::method_a(): {:?}", foo);
}
fn method_b(&self, foo: i32, bar: String) -> String {
println!("<ImplB as SampleTrait>::method_b(): {:?} {:?}", foo, bar);
format!("from ImplB: {}", bar)
}
}
枚舉只需要最少需要處理的每種可能類型:
enum DynSampleTrait {
ImplA(ImplA),
ImplB(ImplB),
}
現在要對此進行調度,您必須執行以下操作:
match value {
DynSampleTrait::ImplA(v) => v.method_a("something"),
DynSampleTrait::ImplB(v) => v.method_a("something"),
}
為了避免不得不重復我們自己,讓我們聲明一個將為我們生成整個match
的宏:
macro_rules! dyn_sample_trait_call {
(($m:expr) $v:ident => $code:block) => {
match $m {
DynSampleTrait::ImplA($v) => $code,
DynSampleTrait::ImplB($v) => $code,
}
}
}
現在我們可以像這樣使用宏:
dyn_sample_trait_call!((value) v => { v.method_a("something") })
value
進入匹配表達式, v
是展開枚舉可能性所持有的內部值的標識符。 這些是分開的,因此如果您不想使用擁有的DynSampleTrait
,您可以匹配參考:
dyn_sample_trait_call!((&value) v => { v.method_a("something") })
( 游樂場)
正如@cdhowie 提到的,您不能從具有Sized
邊界的特征創建特征 object。 相反,您可以創建一個枚舉:
enum MyAlgorithm {
AES128(AES128),
AES192(AES192),
AES256(AES256),
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.