Trait

Rust の型に共通の振る舞いを定義するインターフェース機構

Rust型システム

Trait とは

Trait は Rust の型に共通の振る舞い (メソッド) を定義するインターフェース機構である。TypeScript の interface、Java の interface、Haskell の型クラスに相当する。Rust には継承がなく、Trait でポリモーフィズムを実現する。

基本的な使い方

// Trait の定義
trait Summary {
    fn summarize(&self) -> String;

    // デフォルト実装 (オーバーライド可能)
    fn preview(&self) -> String {
        format!("{}...", &self.summarize()[..50])
    }
}

// Trait の実装
struct Article { title: String, content: String }

impl Summary for Article {
    fn summarize(&self) -> String {
        format!("{}: {}", self.title, &self.content[..100])
    }
}

struct Tweet { username: String, text: String }

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

Trait 境界 (ジェネリクスの制約)

// T は Summary trait を実装している型のみ受け付ける
fn notify(item: &impl Summary) {
    println!("Breaking: {}", item.summarize());
}

// where 句で複数の Trait 境界
fn process<T>(item: &T) -> String
where
    T: Summary + Display + Clone,
{
    format!("{}: {}", item, item.summarize())
}

TypeScript の interface との比較

観点 Rust Trait TypeScript interface
デフォルト実装 あり なし (abstract class で代替)
孤児ルール 外部の型に外部の Trait を実装不可 制限なし
静的ディスパッチ impl Trait (ゼロコスト) -
動的ディスパッチ dyn Trait (vtable) 常に動的
関連型 あり (type Output) なし

標準ライブラリの重要な Trait

Trait 用途
Display 人間向けの文字列表現 println!("{}", value)
Debug デバッグ用の文字列表現 println!("{:?}", value)
Clone 値の複製 value.clone()
Iterator イテレーション for item in collection
From / Into 型変換 String::from("hello")
Serialize / Deserialize JSON 変換 (serde) serde_json::to_string(&value)

derive マクロ

#[derive(Debug, Clone, Serialize, Deserialize)]
struct User {
    id: String,
    name: String,
    email: String,
}
// Debug, Clone, Serialize, Deserialize が自動実装される

Lambda での活用

use serde::{Deserialize, Serialize};

#[derive(Deserialize)]
struct Request { user_id: String }

#[derive(Serialize)]
struct Response { message: String }

// Serialize/Deserialize trait で JSON の変換が自動化

理論と実装の両面から学ぶなら関連書籍が参考になる。

関連用語