Day 4:trait 作為參數與回傳

學習目標

  • impl Trait 當參數
  • 用泛型 + trait bound
  • 回傳 impl Trait

今日重點

impl Trait 當參數

fn notify(item: &impl Summary) {
    println!("Breaking news! {}", item.summarize());
}

&impl Summary:任何實作 Summary 的型別都能傳進來。

泛型 + bound 等價(但語法不同)

fn notify_generic<T: Summary>(item: &T) {
    println!("Breaking news! {}", item.summarize());
}

impl Trait 與泛型不同點:泛型會保留實際型別(可做更多事,如擺進 Vec);impl Trait 是語法糖,呼叫端看不到型別名稱。

多重 bound

fn notify_both<T: Summary + std::fmt::Display>(item: &T) {
    println!("{}: {}", item.summarize(), item);
}

回傳 impl Trait

fn returns_summarizable() -> impl Summary {
    Tweet {
        username: String::from("horse_ebooks"),
        content: String::from("hello"),
    }
}

回傳 impl Trait 表示「回傳某個實現該 trait 的型別,但我不告訴你具體是哪個」。

練習

trait Area { fn area(&self) -> f64; }

struct Circle { r: f64 }
impl Area for Circle { fn area(&self) -> f64 { std::f64::consts::PI * self.r * self.r } }

// 1. 寫 fn print_area(shape: &impl Area)
fn print_area(shape: &impl Area) {
    println!("Area = {}", shape.area());
}

// 2. 寫一個回傳 impl Area 的函式
fn make_circle(r: f64) -> impl Area { Circle { r } }

自我檢查

  • 用 impl Trait 當參數
  • 用泛型 + bound,並知其差別
  • 回傳 impl Trait
  • 會組合多重 bound

深入連結

  • The Book 第 10 章「Traits as Parameters / Returning Types that Implement Traits」