## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# トレイト

トレイトとは任意の型となりうる`Self`に対して定義されたメソッドの集合のことです。同じトレイト内で宣言されたメソッド同士はお互いにアクセスすることができます。

トレイトはあらゆるデータ型に実装することができます。以下の例ではまず`Animal`というメソッドの集合を定義し、その後`Animal`トレイトを`Sheep`というデータ型に対して実装します。これにより`Animal`のメソッドを`Sheep`が使用することが可能になります。

    struct Sheep { naked: bool, name: &'static str }

    trait Animal {
        // 関連関数のシグネチャ
        // `Self` はこのトレイトを実装している型になります。
        fn new(name: &'static str) -> Self;

        // メソッドのシグネチャ
        // これらの関数は文字列を返します。
        fn name(&self) -> &'static str;
        fn noise(&self) -> &'static str;

        // メソッドのデフォルトの挙動を定義することもできます。
        fn talk(&self) {
            println!("{} says {}", self.name(), self.noise());
        }
    }

    impl Sheep {
        fn is_naked(&self) -> bool {
            self.naked
        }

        fn shear(&mut self) {
            if self.is_naked() {
                // メソッドをある型に実装する際に、その型のトレイトメソッドを
                // 使用することができます。
                println!("{} is already naked...", self.name());
            } else {
                println!("{} gets a haircut!", self.name);

                self.naked = true;
            }
        }
    }

    // `Animal`というトレイトを`Sheep`に実装します。
    impl Animal for Sheep {
        // `Self`は実装対象の型：ここでは`Sheep`
        fn new(name: &'static str) -> Sheep {
            Sheep { name: name, naked: false }
        }

        fn name(&self) -> &'static str {
            self.name
        }

        fn noise(&self) -> &'static str {
            if self.is_naked() {
                "baaaaah?"
            } else {
                "baaaaah!"
            }
        }

        // デフォルトのトレイトメソッドはオーバーライドすることができます。
        fn talk(&self) {
            // 例えば、静かに熟考させてみます。
            println!("{} pauses briefly... {}", self.name, self.noise());
        }
    }

    fn main() {
        // この場合、型アノテーションが必須。
        let mut dolly: Sheep = Animal::new("Dolly");
        // TODO ^ ここの型アノテーションを消してみましょう。

        dolly.talk();
        dolly.shear();
        dolly.talk();
    }