特徵物件
特徵物件可接受不同型別的值,舉例來說,在集合中會是這樣:
struct Dog {
name: String,
age: i8,
}
struct Cat {
lives: i8,
}
trait Pet {
fn talk(&self) -> String;
}
impl Pet for Dog {
fn talk(&self) -> String {
format!("Woof, my name is {}!", self.name)
}
}
impl Pet for Cat {
fn talk(&self) -> String {
String::from("Miau!")
}
}
fn main() {
let pets: Vec<Box<dyn Pet>> = vec![
Box::new(Cat { lives: 9 }),
Box::new(Dog { name: String::from("Fido"), age: 5 }),
];
for pet in pets {
println!("Hello, who are you? {}", pet.talk());
}
}
以下是配置 pets 後的記憶體配置:
This slide should take about 10 minutes.
- Types that implement a given trait may be of different sizes. This makes it impossible to have things like
Vec<dyn Pet>in the example above. - 可透過
dyn Pet這個方法向編譯器告知實作Pet的動態大小型別。 - 在本例中,
pets和向量資料分別在堆疊和堆積上分配。這兩個向量元素都是「虛指標」:- A fat pointer is a double-width pointer. It has two components: a pointer to the actual object and a pointer to the virtual method table (vtable) for the
Petimplementation of that particular object. - 名為 Fido 的
Dog資料是name和age欄位。Cat則有lives欄位。
- A fat pointer is a double-width pointer. It has two components: a pointer to the actual object and a pointer to the virtual method table (vtable) for the
- 比較上述範例的輸出內容:
println!("{} {}", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>()); println!("{} {}", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>()); println!("{}", std::mem::size_of::<&dyn Pet>()); println!("{}", std::mem::size_of::<Box<dyn Pet>>());