特征可以用于枚举类型吗



我阅读了trait文档,发现了在structs上使用traits的简洁定义。有可能在enum型上使用性状吗?我看到的答案是否定的,但他们已经3岁了,并没有完全做到我想做的。

我试着这样做:

#[derive(Debug, Copy, Clone)]
pub enum SceneType {
Cutscene,
Game,
Menu,
Pause,
Credits,
Exit,
}
//We want to guarantee every SceneType can be played statically
trait Playable {
fn play();
}
impl Playable for SceneType::Cutscene {
fn play() {}
}
error[E0573]: expected type, found variant `SceneType::Cutscene`
--> src/main.rs:16:19
|
16 | impl Playable for SceneType::Cutscene {
|                   ^^^^^^^^^^^^^^^^^^^
|                   |
|                   not a type
|                   help: you can try using the variant's enum: `SceneType`

我不理解这个错误,因为它引用的枚举在同一个文件中。如果我真的不能在枚举变体上使用特征,有什么方法可以保证任何枚举特征都必须实现某些方法吗?

特征可以用于枚举类型吗?

。事实上,您已经为枚举定义了多个特征;性状DebugCopyClone:

#[derive(Debug, Copy, Clone)]
pub enum SceneType

问题是您没有尝试为枚举实现Playable,而是尝试为枚举的一个变体实现它。枚举变体不是类型

正如错误消息告诉您的:

help: you can try using the variant's enum: `SceneType`
请参阅:
  • 类似结构的枚举可以用作类型吗
  • 有没有一种方法可以将现有结构用作枚举变体

如果你想为Playable实现一个特性(即为所有枚举变体(,那么答案很简单:是的,你可以。Shepmaster的回答详细说明了如何做到这一点。

然而,如果你真的只希望一个枚举变体是Playable,而不希望其他变体,那么Rust并不直接支持这一点,但我看到有一个成语用来模仿它

enum MyEnum {
A(i32, i32),
B(String),
}

您将每个枚举变量显式地实现为一个单独的结构,因此

enum MyEnum {
A(A),
B(B),
}
struct A {
x: i32,
y: i32,
}
struct B {
name: String,
}

然后你可以在没有impl Playable for B的情况下使用impl Playable for A。无论何时要调用它,都要对MyEnum进行模式匹配,如果得到A,则可以根据模式匹配的结果调用示例中的play

我不建议在您编写的每个枚举中使用此模式,因为它确实会使代码变得更加冗长,并且需要一些样板构造函数方法才能使其变得令人满意。但对于有很多选项的复杂枚举,这种模式可以使代码更容易推理,尤其是如果您有很多特性或函数,而这些特性或函数只真正适用于几种枚举可能性。

编辑:真诚道歉;这个答案与无关

每个场景类型都可以静态播放


旧答案

尝试仿制药:

#[derive(Debug, Copy, Clone)]
pub enum SceneType <Cutscene>
where
Cutscene: Playable
{
Cutscene(Cutscene),
Game,
Menu,
Pause,
Credits,
Exit,
}
//We want to guarantee every SceneType can be played statically
// Notice: add `pub` as enum
pub trait Playable {
fn play();
}
// create struct for inner of SceneType::Cutscene 
struct Cutscene {
// ...
}
// impl to specific Cutscene
impl Playable for Cutscene {
fn play() {}
}

测试:

fn main () {
let cutscene = Cutscene{};
let scenetype = SceneType::Cutscene(cutscene);
}

我意识到的一个缺点是泛型是静态的。当一个枚举有多个泛型时,必须指定所有泛型。


enum E <A, B>
where
A: SomeTrait1,
B: SomeTrait2,
{
Enum1(A),
Enum2(B),
}
trait SomeTrait1 {}
trait SomeTrait2 {}
struct S1 {}
impl SomeTrait1 for S1{}
struct S2 {}
impl SomeTrait2 for S2{}
struct X1 {}
impl SomeTrait1 for X1{}
fn main () {
// specify the generics
E::<S1, S2>::Enum1(S1{});
E::<X1, S2>::Enum1(X1{});
//error[E0282]: type annotations needed
//  --> src/main.rs:26:5
//   |
//33 |     E::Enum1(S1{});
//   |     ^^^^^^^^ cannot infer type for type parameter `B` declared on the enum `E`
// E::Enum1(S1{});
// E::Enum1(X1{});
}

最新更新