---
title: struct 与 trait
url: https://doc.liz6.com/rust/02-type-system/03-structs-and-traits
locale: zh
area: rust
tags:
- rust
- 类型系统
date: 2026-06-30
modified: 2026-06-30
description: struct 有三种(具名字段/元组/单元),trait 是 Rust 对"接口"的回答——定义一组方法签名,任何类型可以实现它。derive 宏自动为 struct 生成常见 trait(Clone/Debug/Serialize),orphan rule 限制了"你能为谁实现谁的 trait",防止依赖冲突。
---

# struct 与 trait

> struct 有三种(具名字段/元组/单元),trait 是 Rust 对"接口"的回答——定义一组方法签名,任何类型可以实现它。derive 宏自动为 struct 生成常见 trait(Clone/Debug/Serialize),orphan rule 限制了"你能为谁实现谁的 trait",防止依赖冲突。

## struct: 不仅仅是"数据的集合"

```rust
struct Point { x: f64, y: f64 }      // named fields — 最常见的
struct Color(u8, u8, u8);            // tuple struct — 匿名字段, 适用简单包装
struct AlwaysEqual;                   // unit struct — ZST, 用作 marker 类型
```

tuple struct 适合"新类型包装"——用一个单字段 struct 包装底层类型，赋予新的类型语义，防止误用：

```rust
struct Meters(f64);                  // 不是 f64 — 是 Meters!
struct Feet(f64);

let m = Meters(100.0);
let f = Feet(328.0);
// let sum = m.0 + f.0;              // 可以这么做, 但语义上不应该直接比较
// 编译器不会阻止你, 但类型系统帮你区分"这是米"和"那是英尺"
```

## trait: 行为的契约

trait 定义了"一组方法签名"——任何实现该 trait 的类型都必须提供这些方法：

```rust
trait Summary {
    fn summarize(&self) -> String;    // 必须实现 (no default)
    
    fn default_summary(&self) -> String {  // 有默认实现, 可选 override
        String::from("(Read more...)")
    }
}

impl Summary for Point {
    fn summarize(&self) -> String {
        format!("Point({}, {})", self.x, self.y)
    }
}
```

trait 与 Java/C# 的 interface 类似，但一个重要区别：**你可以为外部类型实现自己的 trait**（但不能为外部类型实现外部 trait——孤规则）。

## Derive: 编译器自动生成代码

```rust
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Point { x: f64, y: f64 }
```

`derive` 要求所有字段也实现了对应 trait。例如 `#[derive(Clone)]` 要求每个字段是 `Clone`。编译器检查这些约束，然后生成模板化的 impl——不需要宏或代码生成工具。

## Orphan Rule (孤规则): 为什么不能随便 impl

```rust
// 你的 crate: my_lib
impl Display for MyType { ... }      // OK: MyType 是你的
impl MyTrait for String { ... }      // OK: MyTrait 是你的
impl Display for Vec<MyType> { ... } // OK: Vec 的参数 MyType 是你的

// impl Display for String { ... }   // ERROR: Display(std) + String(std)
//     两个都在其他 crate 中定义 → orphan rule 禁止
```

这条规则防止了两个 crate 同时为同一个 (type, trait) 组合提供冲突的 impl——如果发生，编译器不知道选哪个，链接阶段的 coherence 检查会报错。这是 Rust trait 系统模块化的核心保证。

## Trait Bounds: 约束泛型

```rust
// 单个 bound — 语法糖
fn notify(item: &impl Summary) { }

// 等价泛型写法
fn notify<T: Summary>(item: &T) { }

// 多个 bounds
fn notify<T: Summary + Display>(item: &T) { }

// where clause — 复杂 bounds 更可读
fn complex<T, U>(t: &T, u: &U) -> T::Output
where
    T: Display + Clone,
    U: Clone + Debug,
    T: Add<U>,
{ ... }
```

## 参考

- **Rust Book**: Chapter 5 (struct), Chapter 10.2 (trait)
- **Rust Reference**: Traits, orphan rules, derive

*Keywords: struct, trait, impl, derive, orphan rule, coherence, trait bound, where clause*
