我正在尝试用 Rust 编写一个函数来构建不同类型的对象(同一特征的所有实现),但我遇到了麻烦,不明白我是否试图做一些非法的事情或者只是不理解正确的语法。 这是一个玩具示例,未编译(animal_factory 函数的三个变体均未编译):
enum Error {
UnknownAnimal,
}
trait Animal {
fn bark(&self);
}
struct Dog {}
impl Dog {
fn new() -> Result<Dog, Error> {
Ok(Dog {})
}
}
impl Animal for Dog {
fn bark(&self) {
println!("Bau! Bau!");
}
}
struct Cat {}
impl Cat {
fn new() -> Result<Cat, Error> {
Ok(Cat {})
}
}
impl Animal for Cat {
fn bark(&self) {
println!("Meow! Meow!");
}
}
/*
fn animal_factory(kind: &str) -> Result<impl Animal, Error> {
match kind {
"cat" => Cat::new(),
"dog" => Dog::new(),
_ => Err(Error::UnknownAnimal),
}
}
*/
/*
fn animal_factory(kind: &str) -> Result<impl Animal, Error> {
match kind {
"cat" => {
return Cat::new();
},
"dog" => {
return Dog::new();
},
_ => {
return Err(Error::UnknownAnimal);
},
}
}
*/
fn animal_factory(kind: &str) -> Result<impl Animal, Error> {
if kind == "cat" {
Cat::new()
} else if kind == "dog" {
Dog::new()
} else {
Err(Error::UnknownAnimal)
}
}
fn main() {
let x = animal_factory("cat").unwrap();
let y = animal_factory("dog").unwrap();
}
有什么见解吗?也许我需要把东西装箱?
最佳答案
impl Animal
如果您尝试返回不同的具体类型(在您的情况下为 Cat
和 Dog
),即使两者都实现了 Animal
,也不会起作用。来自文档:
These types stand in for another concrete type where the caller may only use the methods declared by the specified Trait.
因此,由于类型不匹配,尝试返回 Cat
或 Dog
无法使用 impl Animal
作为返回类型介于这两种具体类型之间。
幸运的是,我们可以轻松地从 Cat
和 Dog
实例创建一种通用类型,同时也实现 Animal
:trait objects 。 Trait 对象使用 dyn Animal
进行注释,而不是 impl Animal
。 Trait 对象的大小是动态调整的,因此我们需要将它们包装到 Box 或其他类型的(智能)指针或引用中:
fn animal_factory(kind: &str) -> Result<Box<dyn Animal>, Error> {
if kind == "cat" {
Ok(Box::new(Cat::new()?))
} else if kind == "dog" {
Ok(Box::new(Dog::new()?))
} else {
Err(Error::UnknownAnimal)
}
}
关于rust - Rust中不同类型的工厂函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76071242/