第11章: トレイト

学習目標

  • トレイトの概念と役割を理解する
  • トレイトの定義と実装方法を学ぶ
  • トレイト境界を使った制約付きジェネリクスを理解する
  • 標準ライブラリの主要なトレイトを把握する
  • ---

    11.1 トレイトの基本

    11.1.1 トレイトとは

    トレイトは、型が持つべき振る舞い(メソッド)を定義する仕組みです:

    // トレイトの定義
    trait Summary {
        fn summarize(&self) -> String;
    }
    
    // 構造体
    struct Article {
        title: String,
        author: String,
        content: String,
    }
    
    // トレイトの実装
    impl Summary for Article {
        fn summarize(&self) -> String {
            format!("{} by {}", self.title, self.author)
        }
    }
    
    fn main() {
        let article = Article {
            title: String::from("Rust入門"),
            author: String::from("Alice"),
            content: String::from("Rustは安全な言語です。"),
        };
    
        println!("{}", article.summarize());
    }
    

    11.1.2 デフォルト実装

    トレイトにはデフォルト実装を含めることができます:

    trait Summary {
        fn summarize(&self) -> String {
            String::from("(続きを読む...)")
        }
    }
    
    struct NewsArticle {
        headline: String,
    }
    
    // デフォルト実装を使用
    impl Summary for NewsArticle {}
    
    fn main() {
        let article = NewsArticle {
            headline: String::from("速報ニュース"),
        };
    
        println!("{}", article.summarize()); // (続きを読む...)
    }
    

    11.2 トレイト境界

    11.2.1 ジェネリクスとトレイト境界

    特定のトレイトを実装した型のみを受け入れる:

    trait Summary {
        fn summarize(&self) -> String;
    }
    
    // トレイト境界を使った関数
    fn notify<T: Summary>(item: &T) {
        println!("速報: {}", item.summarize());
    }
    
    // where句を使った記法
    fn notify_where<T>(item: &T)
    where
        T: Summary,
    {
        println!("速報: {}", item.summarize());
    }
    

    11.2.2 複数のトレイト境界

    use std::fmt::Display;
    
    trait Summary {
        fn summarize(&self) -> String;
    }
    
    // 複数のトレイトを要求
    fn notify<T: Summary + Display>(item: &T) {
        println!("{}", item);
        println!("要約: {}", item.summarize());
    }
    

    11.3 標準トレイト

    11.3.1 よく使うトレイト

    // Debug - デバッグ出力
    #[derive(Debug)]
    struct Point {
        x: i32,
        y: i32,
    }
    
    // Clone - 値の複製
    #[derive(Clone)]
    struct Data {
        value: i32,
    }
    
    // PartialEq - 等値比較
    #[derive(PartialEq)]
    struct Person {
        name: String,
        age: u32,
    }
    
    fn main() {
        let p = Point { x: 10, y: 20 };
        println!("{:?}", p);
    
        let d1 = Data { value: 42 };
        let d2 = d1.clone();
    
        let person1 = Person {
            name: String::from("Alice"),
            age: 30,
        };
        let person2 = Person {
            name: String::from("Alice"),
            age: 30,
        };
        println!("同一人物: {}", person1 == person2);
    }
    

    まとめ

  • トレイトは型が実装すべき振る舞いを定義する
  • トレイト境界でジェネリクスに制約を付けられる
  • deriveマクロで標準トレイトを自動実装できる
  • 次章ではジェネリクスについてさらに深く学びます