Skip to content

Trait 高级特性

> 掌握 impl Trait 返回类型、条件实现和 blanket implementation 等高级用法。

返回实现 Trait 的类型

impl Trait 返回类型

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

// 返回实现 Summary 的类型
fn returns_summarizable() -> impl Summary {
    Tweet {
        username: String::from("horse_ebooks"),
        content: String::from("of course"),
    }
}

fn main() {
    let item = returns_summarizable();
    println!("{}", item.summarize());
}
▶ Run

限制:只能返回单一类型

rust
// ❌ 错误:返回了不同类型
// fn returns_summarizable(switch: bool) -> impl Summary {
//     if switch {
//         Tweet { /* ... */ }
//     } else {
//         NewsArticle { /* ... */ }
//     }
// }

// ✅ 正确:使用 Trait 对象(Box)
fn returns_summarizable(switch: bool) -> Box<dyn Summary> {
    if switch {
        Box::new(Tweet {
            username: String::from("horse_ebooks"),
            content: String::from("of course"),
        })
    } else {
        Box::new(NewsArticle {
            headline: String::from("Breaking"),
            location: String::from("NYC"),
            author: String::from("John"),
            content: String::from("..."),
        })
    }
}
▶ Run

impl Trait vs Box<dyn Trait>

┌─────────────────────────────────────────────────────┐
│      impl Trait vs Box<dyn Trait>                   │
├─────────────────────────────────────────────────────┤
│                                                     │
│  impl Trait(静态分发)                             │
│  ├── 编译时确定类型                                 │
│  ├── 零运行时开销                                   │
│  ├── 只能返回单一类型                             │
│  └── 更高效的调用                                   │
│                                                     │
│  Box<dyn Trait>(动态分发)                         │
│  ├── 运行时确定类型                                 │
│  ├── 有小开销(虚函数表查找)                      │
│  ├── 可以返回不同类型                             │
│  └── 更灵活                                         │
│                                                     │
│  选择:                                              │
│  • 需要返回不同类型 → Box<dyn Trait>               │
│  • 追求性能 → impl Trait                           │
│                                                     │
└─────────────────────────────────────────────────────┘

条件实现

基于泛型约束的实现

rust
use std::fmt::Display;

struct Pair<T> {
    x: T,
    y: T,
}

impl<T> Pair<T> {
    fn new(x: T, y: T) -> Self {
        Self { x, y }
    }
}

// 只有当 T 实现 Display + PartialOrd 时,Pair<T> 才有这个方法
impl<T: Display + PartialOrd> Pair<T> {
    fn cmp_display(&self) {
        if self.x >= self.y {
            println!("较大的是 x: {}", self.x);
        } else {
            println!("较大的是 y: {}", self.y);
        }
    }
}

// 为所有 T 实现 Debug
impl<T: std::fmt::Debug> Pair<T> {
    fn debug_print(&self) {
        println!("{:?}", self);
    }
}

fn main() {
    let p1 = Pair { x: 5, y: 10 };
    p1.cmp_display();        // 较大的是 y: 10
    p1.debug_print();        // Pair { x: 5, y: 10 }

    let p2 = Pair { x: 1.0, y: 2.0 };
    p2.cmp_display();        // 较大的是 y: 2.0
}
▶ Run

blanket implementation

rust
// 为所有实现 Summary 的类型实现 toString
trait Summary {
    fn summarize(&self) -> String;
}

trait ToString {
    fn to_string(&self) -> String;
}

// 为所有实现 Summary 的类型自动实现 ToString
impl<T: Summary> ToString for T {
    fn to_string(&self) -> String {
        self.summarize()
    }
}




---

## 小结

- `impl Trait` 作为返回类型,只能返回单一具体类型
- `Box<dyn Trait>` 可以返回不同类型,但有运行时开销
- 条件实现为满足约束的类型提供特定方法
- blanket implementation 为所有实现某 trait 的类型自动实现另一个 trait
- 静态分发优先,动态分发灵活

## 练习题

详见:[练习题](../../exercises/16-traits)
▶ Run