dynを利用してトレイトを返す - Rust By Example
Description: Rust by Example (RBE) is a collection of runnable examples that illustrate various Rust concepts and standard libraries.

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

# `dyn`を利用してトレイトを返す

Rustのコンパイラはあらゆる関数のリターン型に必要なスペースを知っておく必要があります。つまり、すべての関数は具体的な型を返す必要があるのです。他の言語と違って、`Animal`のようなトレイトがある場合に、`Animal`を返す関数を書くことはできません。なぜなら、そのトレイトの異なる実装はそれぞれ別の量のメモリを必要とするからです。

しかし、簡単な回避策があります。直接トレイトオブジェクトを返す代わりに、`Animal`を 含む `Box`を返すのです。`Box`はヒープ中のメモリへの単なる参照です。参照のサイズは静的に知ることができ、コンパイラは参照がヒープに割り当てられた`Animal`を指していると保証できるので、私たちは関数からトレイトを返すことができます。

ヒープにメモリを割り当てる際、Rustは可能な限り明示的であろうとします。なので、もしあなたの関数がヒープ上のトレイトへのポインタを返す場合、例えば`Box<dyn Animal>`のように、リターン型に`dyn`キーワードをつける必要があります。

    struct Sheep {}
    struct Cow {}

    trait Animal {
        // インスタンスメソッドのシグネチャ
        fn noise(&self) -> &'static str;
    }

    // `Animal`というトレイトを`Sheep`に実装します。
    impl Animal for Sheep {
        fn noise(&self) -> &'static str {
            "baaaaah!"
        }
    }

    // `Cow`に`Animal`トレイトを実装します。
    impl Animal for Cow {
        fn noise(&self) -> &'static str {
            "moooooo!"
        }
    }

    // Animalを実装した何らかの構造体を返します。
    // ただし、コンパイル時にはどの実装か分かりません。
    fn random_animal(random_number: f64) -> Box<dyn Animal> {
        if random_number < 0.5 {
            Box::new(Sheep {})
        } else {
            Box::new(Cow {})
        }
    }

    fn main() {
        let random_number = 0.234;
        let animal = random_animal(random_number);
        println!("You've randomly chosen an animal, and it says {}", animal.noise());
    }