技術筆記 / Rust

Phase 3:模組化與抽象設計

目標:學習 Rust 的抽象機制,寫出高重用性且結構清晰的程式碼。


1. Traits(特徵)— 共享行為的契約

Trait 類似 Java 的 Interface,但功能更強大:

定義與實作 Trait


trait Describable {

    // 必須實作的方法(無預設實作)

    fn describe(&self) -> String;



    // 有預設實作的方法(可以覆寫)

    fn short_description(&self) -> String {

        let full = self.describe();

        if full.len() > 50 {

            format!("{}...", &full[..50])

        } else {

            full

        }

    }

}



struct Dog { name: String, breed: String }

struct Cat { name: String, indoor: bool }



impl Describable for Dog {

    fn describe(&self) -> String {

        format!("{}是一隻{}犬", self.name, self.breed)

    }

}



impl Describable for Cat {

    fn describe(&self) -> String {

        let kind = if self.indoor { "室內" } else { "室外" };

        format!("{}是一隻{}貓", self.name, kind)

    }

}

Trait Bounds(泛型約束)


// 函式接受「任何實作了 Describable 的型別」

fn print_description<T: Describable>(item: &T) {

    println!("{}", item.describe());

}



// 多個 Trait bounds

fn print_debug_and_describe<T: Describable + std::fmt::Debug>(item: &T) {

    println!("{:?} -> {}", item, item.describe());

}



// where 語法(當 bounds 很長時更清晰)

fn complex<T>(item: &T)

where

    T: Describable + Clone + std::fmt::Debug,

{

    // ...

}

動態派送(dyn Trait)


// 編譯期決定型別(靜態派送,零額外開銷)

fn static_dispatch<T: Describable>(item: &T) { ... }



// 執行期決定型別(動態派送,有 vtable 開銷,但更靈活)

fn dynamic_dispatch(item: &dyn Describable) { ... }



// 可以把不同型別的物件放進同一個 Vec!

let animals: Vec<Box<dyn Describable>> = vec![

    Box::new(Dog { name: "旺財".to_string(), breed: "柴犬".to_string() }),

    Box::new(Cat { name: "咪咪".to_string(), indoor: true }),

];


2. Generics(泛型)


// 泛型函式

fn largest<T: PartialOrd>(list: &[T]) -> &T {

    let mut largest = &list[0];

    for item in list {

        if item > largest {

            largest = item;

        }

    }

    largest

}



// 泛型結構體

struct Pair<T> {

    first: T,

    second: T,

}



impl<T: std::fmt::Display + PartialOrd> Pair<T> {

    fn cmp_display(&self) {

        if self.first >= self.second {

            println!("較大的是: {}", self.first);

        } else {

            println!("較大的是: {}", self.second);

        }

    }

}


3. Module System(模組系統)


// src/main.rs 或 src/lib.rs

mod math {

    pub fn add(x: i32, y: i32) -> i32 { x + y }



    pub mod advanced {

        pub fn power(base: i32, exp: u32) -> i32 {

            base.pow(exp)

        }

    }

}



use math::advanced::power;   // 把 power 帶入 scope



fn main() {

    println!("{}", math::add(1, 2));

    println!("{}", power(2, 10));

}

多檔案模組


src/

├── main.rs          ← mod math; 宣告

├── math.rs          ← math 模組的實作(或 math/mod.rs)

└── math/

    ├── mod.rs       ← math 模組的 re-export

    └── advanced.rs  ← math::advanced 子模組

Cargo 依賴管理


# Cargo.toml

[dependencies]

serde = { version = "1.0", features = ["derive"] }

tokio = { version = "1", features = ["full"] }


練習題


cargo run -p phase3_modules --example ex01_traits

cargo run -p phase3_modules --example ex02_generics

cargo run -p phase3_modules --example ex03_iterator_chain

cargo test -p phase3_modules

在 GitHub 看原文