使用 dyn 返回 trait - 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` 返回 trait

Rust 编译器需要知道每个函数的返回类型所需的内存空间。这意味着所有函数都必须返回一个具体类型。与其他语言不同，如果你有一个像 `Animal` 这样的 trait，你不能编写一个直接返回 `Animal` 的函数，因为它的不同实现可能需要不同大小的内存。

然而，有一个简单的解决方法。我们可以让函数返回一个包含 `Animal` 的 `Box`，而不是直接返回 trait 对象。`Box` 本质上是一个指向堆内存的引用。由于引用的大小是静态已知的，且编译器可以保证它指向堆上分配的 `Animal`，这样我们就能从函数中返回一个 trait 了！

Rust 在堆上分配内存时力求明确。因此，如果你的函数以这种方式返回一个指向堆上 trait 的指针，你需要在返回类型中使用 `dyn` 关键字，例如 `Box<dyn Animal>`。

    struct Sheep {}
    struct Cow {}

    trait Animal {
        // 实例方法签名
        fn noise(&self) -> &'static str;
    }

    // 为 `Sheep` 实现 `Animal` trait
    impl Animal for Sheep {
        fn noise(&self) -> &'static str {
            "咩～！"
        }
    }

    // 为 `Cow` 实现 `Animal` trait
    impl Animal for Cow {
        fn noise(&self) -> &'static str {
            "哞~哞~哞~"
        }
    }

    // 返回某个实现了 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());
    }