Возврат типажа с dyn
Компилятору Rust нужно знать сколько места занимает результат
каждой функции. Это обозначает, что все ваши функции имеют
конкретный тип результата. В отличие от других языком, если у вас
есть типаж, например Animal
, то вы не можете
написать функцию, которая вернёт Animal
, по той
причине, что разные реализации этого типажа будут занимать
разное количество памяти.
Однако есть простой обходной путь. Вместо не посредственного
возврата типажа-объекта, наши функции могут возвращать
Box
, который содержит некоторую
реализацию Animal
. box
- это просто
ссылка на какую-то память в куче. Так как размер ссылки известен
статически и компилятор может гарантировать, что она указывает
на аллоцированную в куче реализацию, мы можем вернуть типаж
из нашей функции!
Rust пытается быть предельно явным, когда он выделяет память в
куче. Так что если ваша функция возвращает
указатель-на-типаж-в-куче, вы должны дописать к возвращаемому
типу ключевое слово dyn
, например
Box<dyn Animal>
.
struct Sheep {} struct Cow {} trait Animal { // Сигнатура метода объекта fn noise(&self) -> &'static str; } // Реализуем типаж `Animal` для `Sheep`. impl Animal for Sheep { fn noise(&self) -> &'static str { "baaaaah!" } } // Реализуем типаж `Animal` для `Cow`. 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!("Вы выбрали случайное животное и оно говорит {}", animal.noise()); }