Возврат типажа с 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());
}