Rust特徵與泛型區別點
阿新 • • 發佈:2020-08-16
1. Rust的特徵與泛型
1.1 先上特徵程式碼:
use std::boxed::Box; // 定義一個特徵 pub trait Animal{ fn bark(&self); } pub struct Dog{ pub name: String, } pub struct Chicken{ pub name: String, } // 實現一個特徵 impl Animal for Dog{ fn bark(&self){ println!("{} : wang wang wang !",&self.name) } } // 實現特徵 impl Animal for Chicken{ fn bark(&self){ println!("{} : ji ji ji ~",&self.name) } } pub struct Zoo{ // 用一個list裝動物 pub components: Vec<Box<dyn Animal>>, } // 給Zoo實現一個方法 impl Zoo{ pub fn run(&self){ for c in self.components.iter() { c.bark(); } } }
為什麼先上程式碼? 因為這就要先從程式碼說起來了,把程式碼貼出來和Java的程式碼進行對比可能更加明確。
從程式碼看來,Rust中的trait和Java中的介面非常相似,都是用來定義一組行為。
執行程式碼:
use animal::{Zoo,Chicken,Dog}; fn main() { // 例項化結構體,並放入了兩個物件 let zoo = Zoo{ components: vec![ Box::new(Chicken{ name: String::from("xiao ji"), }), Box::new(Dog{ name: String::from("旺財"), }), ], }; zoo.run(); }
執行結果:
xiao ji is bark
旺財 is bark
1.2 泛型程式碼
上程式碼:
pub trait Animal{ fn bark(&self); } pub struct Dog{ pub name: String, } pub struct Chicken{ pub name: String, } impl Animal for Dog{ fn bark(&self){ println!("{} is bark",&self.name) } } impl Animal for Chicken{ fn bark(&self){ println!("{} is bark",&self.name) } } // 把特徵換成泛型 pub struct Zoo<T: Animal>{ pub components: Vec<T>, } impl <T> Zoo<T> where T: Animal{ pub fn run(&self){ for c in self.components.iter() { c.bark(); } } }
程式碼沒有大的改變,將集合中使用trait改為泛型。
主程式碼不變,然後編譯程式碼,出現如下錯誤
160 | pub struct Box<T: ?Sized>(Unique<T>);
| ------------------------------------- doesn't satisfy `std::boxed::Box<animal::Chicken>: animal::Animal`
|
= note: the method `run` exists but the following trait bounds were not satisfied:
`std::boxed::Box<animal::Chicken>: animal::Animal`
1.2 出現問題的原因?
Rust與Java不同, 在Java中,可能介面和泛型,都可以使用,代表一類型別,但是在Rust中,竟然不可以,這是為什麼呢?
在Rust中, 由於安全性考慮,在使用泛型的時候,型別由第一個個物件確定了, 在編譯的時候,發現後邊的型別與第一個型別不同,則會出現這樣的錯誤。
1.3 結論
在Rust中使用泛型和特徵的時候要注意,可能特種更符合Java中的介面與泛型。而Rust泛型由於在編譯的時候確定了型別,反而有些像陣列,確定了唯一型別,只能放一種型別。