使用 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());
}