このページの目次
struct と trait
struct には3種類(名前付きフィールド/タプル/ユニット)があり、trait は Rust における「インターフェース」への回答です——一連のメソッドシグネチャを定義し、任意の型がそれを実装できます。derive マクロは struct に対して一般的な trait(Clone/Debug/Serialize)を自動生成し、orphan rule(孤ルール)は「誰が誰の trait を実装できるか」を制限し、依存関係の競合を防ぎます。
struct: 「データの集合体」以上のもの
// named fields — 最も一般的
; // tuple struct — 名前なしフィールド、単純なラップに適す
; // unit struct — ZST、マーカー型として使用
タプル構造体は「新しい型のラップ」に適しています——単一フィールドの struct で基盤となる型をラップし、新しい型のセマンティクスを与えて誤用を防ぎます:
; // f64 ではない — Meters だ!
;
let m = Meters;
let f = Feet;
// let sum = m.0 + f.0; // こうすることは可能だが、セマンティクスとして直接比較すべきではない
// コンパイラはこれを阻止しないが、型システムが「これはメートル」「あれはフィート」を区別してくれる
trait: 振る舞いの契約
trait は「一連のメソッドシグネチャ」を定義します——この trait を実装するあらゆる型は、これらのメソッドを提供しなければなりません:
trait は Java/C# の interface に似ていますが、重要な違いがあります:外部型に対して独自の trait を実装できる(ただし、外部型に対して外部 trait を実装することはできません——これを孤ルールと呼びます)。
Derive: コンパイラによる自動コード生成
derive は、すべてのフィールドが対応する trait を実装していることを要求します。例えば #[derive(Clone)] は、各フィールドが Clone であることを要求します。コンパイラはこれらの制約をチェックし、テンプレート化された impl を生成します——マクロやコード生成ツールは不要です。
Orphan Rule (孤ルール): なぜ気軽に impl できないのか
// 自前の crate: my_lib
// OK: MyType は自前
// OK: MyTrait は自前
// OK: Vec の引数 MyType は自前
// impl Display for String { ... } // ERROR: Display(std) + String(std)
// 両方とも他の crate で定義されている → orphan rule により禁止
このルールは、2つの crate が同じ (型, trait) の組み合わせに対して競合する impl を同時に提供することを防ぎます——もし発生した場合、コンパイラはどちらを選ぶべきか判断できず、リンク時の整合性チェックでエラーになります。これは Rust の trait システムにおけるモジュール化の核心的な保証です。
Trait Bounds: ジェネリクスへの制約
// 単一の bound — 構文糖衣
// 等価なジェネリック記法
// 複数の bounds
// where 節 — 複雑な bounds でより可読性向上
参考
- Rust Book: 第5章 (struct)、第10.2章 (trait)
- Rust Reference: Traits, orphan rules, derive
Keywords: struct, trait, impl, derive, orphan rule, coherence, trait bound, where clause