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

The Rust compiler needs to know how much space every function's return type requires. This means all your functions have to return a concrete type. Unlike other languages, if you have a trait like Animal, you can't write a function that returns Animal, because its different implementations will need different amounts of memory.

しかし、簡単な回避策があります。直接トレイトオブジェクトを返す代わりに、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());
}