dynでトレイトを返す
Rustコンパイラは返り値にどのくらいスペースが必要か事前に把握する必要があります。これは、すべての関数が具象型を返す必要があることを意味します。他の言語と違って、
異なる実装は異なるメモリ容量を持つため、Animalのようなトレイトを持っていたとしても、Animalを返す関数は書けません。
しかし、これには簡単な回避策があります。トレイとオブジェクトを直接返す代わりに、Animalを含むBox型を返せばよいのです。boxはヒープメモリの参照に
過ぎませんが、参照は固定されたサイズを持っている上、コンパイラはヒープに格納されたAnimalの参照を返すことが保証されているため、関数からトレイトを返すことが
できます!
Rustはヒープへのメモリ確保ができるだけ明示的になるようにしてきました。そのため、ヒープに確保されたトレイトの参照を返すときも、
返す型をdynキーワードで明示しなければいけません (例えばBox<dyn Animal>)
struct Sheep {} struct Cow {} trait Animal { // インスタンスメソッド fn noise(&self) -> &'static str; } // `Sheep`に`Animal`トレイトを実装する。 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()); }