---
title: struct と trait
url: https://doc.liz6.com/ja/rust/02-type-system/03-structs-and-traits
locale: ja
area: rust
tags:
- rust
- type-system
date: 2026-06-30
modified: 2026-07-16
description: struct には3種類（名前付きフィールド/タプル/ユニット）があり、trait は Rust における「インターフェース」への回答です——一連のメソッドシグネチャを定義し、任意の型がそれを実装できます。derive マクロは struct に対して一般的な trait（Clone/Debug/Serialize）を自動生成し、orphan rule（孤ルール）は「誰が誰の trait を実装できるか」を制限し、依存関係の競合を防ぎます。
---

# struct と trait

> struct には3種類（名前付きフィールド/タプル/ユニット）があり、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、マーカー型として使用
```

タプル構造体は「新しい型のラップ」に適しています——単一フィールドの 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;    // 実装必須 (デフォルトなし)
    
    fn default_summary(&self) -> String {  // デフォルト実装あり、上書きは任意
        String::from("(続きを読む...)")
    }
}

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 により禁止
```

このルールは、2つの crate が同じ (型, trait) の組み合わせに対して競合する impl を同時に提供することを防ぎます——もし発生した場合、コンパイラはどちらを選ぶべきか判断できず、リンク時の整合性チェックでエラーになります。これは 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 節 — 複雑な bounds でより可読性向上
fn complex<T, U>(t: &T, u: &U) -> T::Output
where
    T: Display + Clone,
    U: Clone + Debug,
    T: Add<U>,
{ ... }
```

## 参考

- **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*
