使用 dyn
返回特征
Rust 编译器需要知道每个函数的返回类型所需的空间大小。这意味着所有函数都必须返回一个具体的类型。与其他语言不同,如果你有一个像 Animal
这样的特征,你不能编写一个返回 Animal
的函数,因为它的不同实现需要不同的内存量。
然而,有一个简单的解决方法。我们的函数不直接返回特征对象,而是返回一个包含一些 Animal
的 Box
。box
只是指向堆中某些内存的引用。因为引用的大小是静态已知的,并且编译器可以保证它指向堆分配的 Animal
,所以我们可以从函数中返回一个特征!
每当在堆上分配内存时,Rust 都会尽量做到显式。因此,如果你的函数以这种方式返回指向堆上特征的指针,则需要使用 dyn
关键字编写返回类型,例如 Box<dyn Animal>
。
struct Sheep {} struct Cow {} trait Animal { // Instance method signature fn noise(&self) -> &'static str; } // Implement the `Animal` trait for `Sheep`. impl Animal for Sheep { fn noise(&self) -> &'static str { "baaaaah!" } } // Implement the `Animal` trait for `Cow`. impl Animal for Cow { fn noise(&self) -> &'static str { "moooooo!" } } // Returns some struct that implements Animal, but we don't know which one at compile time. 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()); }