1. 程式人生 > 實用技巧 >Rust特徵與泛型區別點

Rust特徵與泛型區別點

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泛型由於在編譯的時候確定了型別,反而有些像陣列,確定了唯一型別,只能放一種型別。