[英]Does Rust erase generic types or not?
Rust 中是否存在泛型類型擦除(如 Java)? 我無法找到明確的答案。
當您使用泛型函數或泛型類型時,編譯器會為每個不同的類型參數集生成一個單獨的實例(我相信生命周期參數會被忽略,因為它們對生成的代碼沒有影響)。 這個過程稱為單態化。 例如, Vec<i32>
和Vec<String>
是不同的類型,因此Vec<i32>::len()
和Vec<String>::len()
是不同的函數。 這是必要的,因為Vec<i32>
和Vec<String>
具有不同的內存布局,因此需要不同的機器碼! 因此,不,沒有類型擦除。
如果我們使用Any::type_id()
,如下例所示:
use std::any::Any;
fn main() {
let v1: Vec<i32> = Vec::new();
let v2: Vec<String> = Vec::new();
let a1 = &v1 as &dyn Any;
let a2 = &v2 as &dyn Any;
println!("{:?}", a1.type_id());
println!("{:?}", a2.type_id());
}
我們為Vec
兩個實例獲得不同的類型 ID。 這支持Vec<i32>
和Vec<String>
是不同類型的事實。
然而,Rust 中的反射能力是有限的; Any
幾乎就是我們現在所擁有的。 您無法獲得有關運行時值類型的更多信息,例如其名稱或其成員。 為了能夠使用Any
,您必須將其Any::downcast_ref()
使用Any::downcast_ref()
或Any::downcast_mut()
為編譯時已知的類型。
Rust 確實通過dyn Trait
以虛方法分派的形式進行類型擦除,這允許您擁有一個Vec
,其中元素具有不同的具體類型:
fn main() {
let list: Vec<Box<dyn ToString>> = vec![Box::new(1), Box::new("hello")];
for item in list {
println!("{}", item.to_string());
}
}
請注意,編譯器要求您手動裝箱元素,因為它必須在編譯時知道每個值的大小。 您可以使用Box
,無論它指向什么,它都具有相同的大小,因為它只是一個指向堆的指針。 您還可以使用&
-references:
fn main() {
let list: Vec<&dyn ToString> = vec![&1, &"hello"];
for item in list {
println!("{}", item.to_string());
}
}
但是,請注意,如果您使用&
-references,您可能會遇到生命周期問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.