根据 this answer至 this questions我需要执行以下操作以返回 Trait
的实例:
trait Shader {}
struct MyShader;
impl Shader for MyShader {}
struct GraphicsContext;
impl GraphicsContext {
fn create_shader(&self) -> impl Shader {
let shader = MyShader;
shader
}
}
但是当我尝试这样做时:
pub trait Component { }
struct Kind {}
struct Location {}
impl Component for Kind {}
impl Component for Location {}
pub fn get(comp_name: &String) -> impl Component {
match comp_name.as_ref() {
"kind" => Kind,
"location" => Location
}
}
我只是得到错误:
error[E0423]: expected value, found struct
Kind
--> src/main.rs:17:24| 17 | "kind" => Kind, | ^^^^ did you mean `Kind { /* fields */ }`?
error[E0423]: expected value, found struct
Location
--> src/main.rs:18:24| 18 | "location" => Location | ^^^^^^^^ did you mean `Location { /* fields */ >}`?
最佳答案
那个impl Component
因为返回类型基本上是 T where T: Component
, 其中T
由函数本身而不是调用者选择。
T
可以是Kind
, T
可以是Location
,但是 T
不能同时兼顾。
两种解决方案:
动态地:返回
Box<dyn Component>
并返回Box::new(Kind{})
或Box::new(Location{})
.缺点是它会导致堆分配。静态地,通过返回
enum
:
enum KindOrLocation {
Kind(Kind),
Location(Location),
}
使它可以用作 Component
, 你可以实现 Deref<Target = dyn Component>
:
impl Deref for KindOrLocation {
type Target = dyn Component + 'static;
fn deref(&self) -> &Self::Target {
match self {
KindOrLocation::Kind(x) => x,
KindOrLocation::Location(x) => x,
}
}
}
这里的缺点是您必须编写此样板代码。
顺便说一句:
- 如果你用
{}
定义结构喜欢struct Kind {}
,您通过编写Kind{}
创建它的一个对象,不只是Kind
. - 您需要处理
_
你的比赛中的案例:_ => panic!()
什么的。 - 不要拿
&String
, 但取&str
反而。然后它适用于两者&String
和&str
.
关于Rust 不允许我从匹配中返回一个类型的实例,一直认为我正在尝试返回一个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55540512/