Skip to content

traits.rs

文件信息

  • 📄 原文件:03_traits.rs
  • 🔤 语言:rust

完整代码

rust
// ============================================================
//                      Trait(特征)
// ============================================================
// Trait 定义共享行为,类似其他语言的接口(interface)
// 但 Rust 的 trait 更强大:可以有默认实现、泛型约束、关联类型
//
// 【类比】
//   - Go 的 interface(但 Rust trait 需要显式实现)
//   - Java 的 interface(但可以有默认方法和关联类型)
//   - Haskell 的 typeclass

// ----------------------------------------------------------
// 1. 定义 Trait
// ----------------------------------------------------------
trait Summary {
    // 必须实现的方法(没有函数体)
    fn summarize(&self) -> String;

    // 有默认实现的方法(可以覆盖)
    fn preview(&self) -> String {
        format!("(预览: {}...)", &self.summarize()[..20.min(self.summarize().len())])
    }
}

// ----------------------------------------------------------
// 2. 为类型实现 Trait
// ----------------------------------------------------------
struct Article {
    title: String,
    author: String,
    content: String,
}

impl Summary for Article {
    fn summarize(&self) -> String {
        format!("{}, 作者: {}", self.title, self.author)
    }
    // preview 使用默认实现
}

struct Tweet {
    username: String,
    content: String,
}

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

    // 覆盖默认实现
    fn preview(&self) -> String {
        format!("推文来自 @{}", self.username)
    }
}

// ----------------------------------------------------------
// 3. 常用的标准库 Trait
// ----------------------------------------------------------

// Display: 控制 {} 格式化输出
use std::fmt;

struct Point {
    x: f64,
    y: f64,
}

impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

fn main() {
    println!("=== Trait ===");

    // ----------------------------------------------------------
    // 基本使用
    // ----------------------------------------------------------
    let article = Article {
        title: String::from("Rust 学习指南"),
        author: String::from("张三"),
        content: String::from("Rust 是一门系统编程语言..."),
    };

    let tweet = Tweet {
        username: String::from("rustlang"),
        content: String::from("Rust 1.75 发布了!"),
    };

    println!("文章: {}", article.summarize());
    println!("文章预览: {}", article.preview());
    println!("推文: {}", tweet.summarize());
    println!("推文预览: {}", tweet.preview());

    // ----------------------------------------------------------
    // Trait 作为参数(静态分发 vs 动态分发)
    // ----------------------------------------------------------
    println!("\n=== Trait 作为参数 ===");

    // 方式1: impl Trait(静态分发,编译时确定类型,有内联优化)
    // 【推荐】大多数情况用这种
    notify_static(&article);
    notify_static(&tweet);

    // 方式2: &dyn Trait(动态分发,运行时通过 vtable 查找)
    // 【适用】需要在运行时存储不同类型时
    notify_dynamic(&article);

    // 动态分发的典型用法:存储不同类型的集合
    let items: Vec<Box<dyn Summary>> = vec![
        Box::new(Article {
            title: String::from("标题1"),
            author: String::from("作者1"),
            content: String::from("内容1"),
        }),
        Box::new(Tweet {
            username: String::from("user1"),
            content: String::from("推文内容"),
        }),
    ];

    println!("\n动态集合:");
    for item in &items {
        println!("  {}", item.summarize());
    }

    // ----------------------------------------------------------
    // Trait Bound(约束)
    // ----------------------------------------------------------
    println!("\n=== Trait Bound ===");

    // 多重约束
    let p = Point { x: 3.0, y: 4.0 };
    print_info(&p);

    // where 子句(复杂约束时更清晰)
    let a = String::from("hello");
    let b = String::from("world");
    println!("较长的: {}", longer_display(&a, &b));

    // ----------------------------------------------------------
    // 返回 impl Trait
    // ----------------------------------------------------------
    let item = create_summarizable();
    println!("\n返回 impl Trait: {}", item.summarize());

    // ----------------------------------------------------------
    // Trait 继承
    // ----------------------------------------------------------
    println!("\n=== Trait 继承 ===");

    let user = WebUser {
        id: 1,
        name: String::from("张三"),
        email: String::from("[email protected]"),
    };

    // Printable 继承了 Display,所以可以用 {} 格式化
    print_item(&user);
    println!("用户: {}", user); // Display
    user.print();               // Printable

    // ----------------------------------------------------------
    // 关联类型
    // ----------------------------------------------------------
    println!("\n=== 关联类型 ===");

    let mut counter = Counter::new(5);
    print!("计数器: ");
    while let Some(val) = counter.next() {
        print!("{} ", val);
    }
    println!();

    // ----------------------------------------------------------
    // 常用标准库 Trait 演示
    // ----------------------------------------------------------
    println!("\n=== 常用 Trait ===");

    // Clone + Copy
    let p1 = Point { x: 1.0, y: 2.0 };
    let _p2 = p1;  // Point 没有实现 Copy,所以这是移动
    // println!("{}", p1);  // 错误!p1 已移动

    // PartialEq + Eq
    let a = Temperature(36.6);
    let b = Temperature(36.6);
    let c = Temperature(37.5);
    println!("{} == {} ? {}", a.0, b.0, a == b);
    println!("{} < {} ? {}", a.0, c.0, a < c);

    // Default
    let config = Config::default();
    println!("默认配置: host={}, port={}, debug={}",
             config.host, config.port, config.debug);

    // From/Into
    let greeting: Greeting = "你好".into();
    println!("From/Into: {}", greeting.0);

    let greeting2 = Greeting::from("世界");
    println!("From: {}", greeting2.0);

    println!("\n=== Trait 结束 ===");
}

// ----------------------------------------------------------
// impl Trait 参数(静态分发)
// ----------------------------------------------------------
fn notify_static(item: &impl Summary) {
    println!("[静态] 通知: {}", item.summarize());
}

// ----------------------------------------------------------
// dyn Trait 参数(动态分发)
// ----------------------------------------------------------
fn notify_dynamic(item: &dyn Summary) {
    println!("[动态] 通知: {}", item.summarize());
}

// ----------------------------------------------------------
// 多重 Trait Bound
// ----------------------------------------------------------
fn print_info(item: &(impl fmt::Display + fmt::Debug)) {
    println!("Display: {}", item);
    println!("Debug: {:?}", item);
}

// 实现 Debug for Point
impl fmt::Debug for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Point{{ x: {}, y: {} }}", self.x, self.y)
    }
}

// ----------------------------------------------------------
// where 子句
// ----------------------------------------------------------
fn longer_display<T>(a: &T, b: &T) -> &T
where
    T: fmt::Display + PartialOrd,
{
    if a >= b { a } else { b }
}

// ----------------------------------------------------------
// 返回 impl Trait
// ----------------------------------------------------------
fn create_summarizable() -> impl Summary {
    Tweet {
        username: String::from("bot"),
        content: String::from("自动生成的内容"),
    }
}

// ----------------------------------------------------------
// Trait 继承
// ----------------------------------------------------------
trait Printable: fmt::Display {
    fn print(&self) {
        println!("打印: {}", self);
    }
}

struct WebUser {
    id: u64,
    name: String,
    email: String,
}

impl fmt::Display for WebUser {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}(#{})", self.name, self.id)
    }
}

impl Printable for WebUser {}  // 使用 print 的默认实现

fn print_item(item: &impl Printable) {
    item.print();
}

// ----------------------------------------------------------
// 关联类型(Iterator trait)
// ----------------------------------------------------------
struct Counter {
    count: u32,
    max: u32,
}

impl Counter {
    fn new(max: u32) -> Counter {
        Counter { count: 0, max }
    }
}

impl Iterator for Counter {
    type Item = u32;  // 关联类型

    fn next(&mut self) -> Option<Self::Item> {
        if self.count < self.max {
            self.count += 1;
            Some(self.count)
        } else {
            None
        }
    }
}

// ----------------------------------------------------------
// 常用标准库 Trait 实现
// ----------------------------------------------------------

// PartialEq + PartialOrd
#[derive(Debug, PartialEq, PartialOrd)]
struct Temperature(f64);

// Default
struct Config {
    host: String,
    port: u16,
    debug: bool,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            host: String::from("localhost"),
            port: 8080,
            debug: false,
        }
    }
}

// From/Into
struct Greeting(String);

impl From<&str> for Greeting {
    fn from(s: &str) -> Self {
        Greeting(s.to_string())
    }
}

💬 讨论

使用 GitHub 账号登录后即可参与讨论

基于 MIT 许可发布