Rust學習(19):泛型【不太理解。。。】

泛型單態化沒有運行時開銷

1、泛型數據結構

枚舉泛型

enum Option<T> {
    Some(T),
    None,
}

結構體泛型

泛型結構體定義

struct Point<T>{
    x:T,
    y:T,
}  //字段 x 和 y 都是 相同類型的

struct PointTU<T, U>{
    x:T,
    y:U,
}  //字段  x 和 y 可以有不同類型

fn main() {
    let int = Point{x:4, y:4};
    let fl = Point{x:4.4, y:5.4};

    println!("{}, {}", int.x, fl.y);

    let hun = PointTU{x:"44", y:4.5};
    println!("{}, {}", hun.x, hun.y);

}

泛型結構體方法

struct Point<T>{
    x:T,
    y:T,
}  //字段 x 和 y 都是 相同類型的

impl <T> Point<T>{
    fn get_x(&self)->&T{
        return &self.x;
    }
}

impl Point<f32>{
    //計算點實例與座標 (0.0, 0.0) 之間的距離,並使用了只能用於浮點型的數學運算符。
    fn distiance_from_origin(&self)->f32{
        return (self.x.powi(2) + self.y.powi(2)).sqrt();
    }
}


fn main() {
    let int:Point<i32> = Point{x:4, y:4};
    let fl:Point<f32>  = Point{x:2.0, y:2.0};

    
    println!("{}, {}, {}, {}", int.x, fl.y, int.get_x(), fl.distiance_from_origin());
    
}

實例2:

struct Point<T, U>{
    x:T,
    y:U,
}

impl <T, U> Point<T, U>{
    fn mixup<V, W>(self, other:Point<V, W>)->Point<T, W>{
        Point{
            x:self.x,
            y:other.y,
        }
    }
}
fn main() {
    let p1 = Point{x:5, y:10.4};
    let p2 = Point{x:"hello", y:'C'};

    let p3 = p2.mixup(p1);

    println!("{:?}, {}", p3.x, p3.y)
}

2、trait

什麼是trait

trait用來實現多態。類似C++中的接口

pub trait Summary{
    fn summarize(&self)->String;
}

pub struct NewsArticle{
    pub headline:String,
    pub location:String,
    pub author:String,
    pub content:String,
}

pub struct Tweet{
    pub username:String,
    pub content:String,
    pub reply:bool,
    pub retweet:bool,
}

impl Summary for NewsArticle{
  fn summarize(&self)->String{
      format!("{}, by {} ({})", self.headline, self.author, self.location)
  }
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        return format!("{}: {}", self.username, self.content);
    }
}

fn main() {
   let tweet = Tweet{
       username:String::from("horse_ebooks"),
       content:String::from("I have nothing"),
       reply:false,
       retweet:false,
   };

   println!("{}", tweet.summarize());

    let article = NewsArticle {
    headline: String::from("NewsArticle_headline"),
    location: String::from("Pittsburgh, PA, USA"),
    author: String::from("Iceburgh"),
    content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."),
   };

    println!("{}", article.summarize());
}

在這裏插入圖片描述

默認trait

默認指定行爲

pub trait Summary{
    fn summarize(&self)->String{
        return String::from("默認實現");
    }
}

pub struct NewsArticle{
    pub headline:String,
    pub location:String,
    pub author:String,
    pub content:String,
}

pub struct Tweet{
    pub username:String,
    pub content:String,
    pub reply:bool,
    pub retweet:bool,
}

impl Summary for NewsArticle{  //必須寫
		//因爲沒有實現summarize所以會調用默認實現的trait
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        return format!("{}: {}", self.username, self.content);
    }
}

fn main() {
   let tweet = Tweet{
       username:String::from("horse_ebooks"),
       content:String::from("I have nothing"),
       reply:false,
       retweet:false,
   };

    let article = NewsArticle {
    headline: String::from("NewsArticle_headline"),
    location: String::from("Pittsburgh, PA, USA"),
    author: String::from("Iceburgh"),
    content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."),
   };


    println!("{}", tweet.summarize());
    println!("{}", article.summarize());
}

在這裏插入圖片描述

trait作爲參數

pub trait Summary{
    fn ari_authon(&self)->String;
    fn summarize(&self)->String{
        return String::from("默認實現");
    }
}


pub struct NewsArticle{
    pub headline:String,
    pub location:String,
    pub author:String,
    pub content:String,
}

pub struct Tweet{
    pub username:String,
    pub content:String,
    pub reply:bool,
    pub retweet:bool,
}

impl Summary for NewsArticle{  //must
    fn ari_authon(&self)->String{
        return format!("{}", self.author);
   }
}

pub fn notify_bound<T:Summary>(item:T){
    println!("參數:{}", item.ari_authon())
}


fn main() {
    let article = NewsArticle {
    headline: String::from("NewsArticle_headline"),
    location: String::from("Pittsburgh, PA, USA"),
    author: String::from("Iceburgh"),
    content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."),
   };


    println!("{}, {}", article.summarize(), article.ari_authon());

    notify_bound(article)
}

trait bound語法糖

pub trait Summary{
    fn ari_authon(&self)->String;
    fn summarize(&self)->String{
        return String::from("默認實現");
    }
}


pub struct NewsArticle{
    pub headline:String,
    pub location:String,
    pub author:String,
    pub content:String,
}

pub struct Tweet{
    pub username:String,
    pub content:String,
    pub reply:bool,
    pub retweet:bool,
}

impl Summary for NewsArticle{  //must
    fn ari_authon(&self)->String{
        return format!("{}", self.author);
   }
}

pub fn notify(item:impl Summary){ //在 notify 函數體中,可以調用任何來自 Summary trait 的方法
    println!("參數:{}", item.summarize())
}

fn main() {
    let article = NewsArticle {
    headline: String::from("NewsArticle_headline"),
    location: String::from("Pittsburgh, PA, USA"),
    author: String::from("Iceburgh"),
    content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."),
   };


    println!("{}, {}", article.summarize(), article.ari_authon());

    notify(article);  //值的所有權
}

適用

pub fn notify(item1: impl Summary, item2: impl Summary) 
pub fn notify<T: Summary>(item1: T, item2: T) 

trait bound實現PartialOrd trait和 Copy trait:

//爲了只對實現了 Copy 的類型調用這些代碼,可以在 T 的 trait bounds 中增加 Copy:error[E0508]: cannot move out of type `[T]`, a non-copy slice
fn largest<T:PartialOrd + Copy>(list:&[T])->T{ //PartialOrd trait (允許比較),or:error[E0369]: binary operation `>` cannot be applied to type `T`
   let mut largest = list[0]; //i32 和 char 這樣的類型是已知大小的並可以儲存在棧上,所以他們實現了 Copy trait
   //largest 函數改成使用泛型後,現在 list 參數的類型就有可能是沒有實現 Copy trait 的。
   //可能不能將 list[0] 的值移動到 largest 變量中
   //只要傳遞給 largest 的 slice 值的類型實現了 PartialOrd 和 Copy 這兩個 trait
   for &item in list.iter(){
       if item > largest{
           largest = item;
       }
   }

   largest
}



fn main() {
   let number_list = vec![34, 50, 25, 100, 65];

   let result = largest(&number_list);
   println!("{}", result);

   let char_list = vec!['y', 'm', 'a', 'q'];

   let result = largest(&char_list);
   println!("The largest char is {}", result);
}

trait作爲返回值

pub trait Summary{
    fn ari_authon(&self)->String;
    fn summarize(&self)->String{
        return String::from("默認實現");
    }
}


pub struct NewsArticle{
    pub headline:String,
    pub location:String,
    pub author:String,
    pub content:String,
}

impl Summary for NewsArticle{  //must
    fn ari_authon(&self)->String{
        return format!("{}", self.author);
   }
}


fn returns_summarizable() -> impl Summary {
   NewsArticle {
    headline: String::from("NewsArticle_headline"),
    location: String::from("Pittsburgh, PA, USA"),
    author: String::from("Iceburgh"),
    content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."),
    }
}

fn main() {
    let al = returns_summarizable();

    println!("{}, {}", al.summarize(), al.ari_authon());
}

只適用於返回單一類型的情況。例如,這樣就 不行:

fn returns_summarizable(switch: bool) -> impl Summary {
    if switch {
        NewsArticle {
            headline: String::from("Penguins win the Stanley Cup Championship!"),
            location: String::from("Pittsburgh, PA, USA"),
            author: String::from("Iceburgh"),
            content: String::from("The Pittsburgh Penguins once again are the best
            hockey team in the NHL."),
        }
    } else {
        Tweet {
            username: String::from("horse_ebooks"),
            content: String::from("of course, as you probably already know, people"),
            reply: false,
            retweet: false,
        }
    }
}

參考:https://kaisery.github.io/trpl-zh-cn/ch09-01-unrecoverable-errors-with-panic.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章