如何使包含枚举泛型的结构优于枚举变体?

Nur*_*yev 8 types rust

请看一下代码:

struct Human {
  name: String,
  profession: Profession,
}

enum Profession {
  Doctor,
  Teacher
}

struct Family {
  family_doctor: // How to express type that will mean Human (because name matters) of profession Doctor?
}

Run Code Online (Sandbox Code Playgroud)

是否可以通过以Human某种方式进行泛型并将变体作为字段Doctor的类型参数传递来做到这一点?profession如果没有,那么您建议的这种关系最接近的解决方法是什么?

请注意,这个问题可能看起来与旧问题重复。但首先,Rust 不断发展,其次,我要求一种解决方法。

tre*_*tcl 7

也许最简单的事情就是创建Profession一个特征而不是一个enum,并使每个成为Profession一个单元结构:

struct Human<P: ?Sized + Profession> {
  name: String,
  profession: P,
}

struct Doctor;
struct Teacher;

trait Profession {}

impl Profession for Doctor {}
impl Profession for Teacher {}

struct Family {
  family_doctor: Human<Doctor>,
}
Run Code Online (Sandbox Code Playgroud)

大多数接受人类的函数都可以使用泛型或impl Profession

fn into_name<P: Profession>(any_human: Human<P>) -> String {
    any_human.name
}
Run Code Online (Sandbox Code Playgroud)

编写接受不同类型 Human 的函数的另一种方法是使用动态调度。如果您这样做,则对 a 的任何访问都Human必须通过指针完成,例如Box<Human<dyn Profession>>or &Human<dyn Profession>(注意这是有效的,因为P: ?Sized在 的定义中Human):

fn into_name_dyn(any_human: Box<Human<dyn Profession>>) -> String {
    any_human.name
}
Run Code Online (Sandbox Code Playgroud)

另一种可能性是实现ProfessionforBox<dyn Profession>并将其用作类型参数。这会将指针放入其中Human,因此只有Profession在其后面:

impl<P: ?Sized + Profession> Profession for Box<P> {}

fn into_name_box(any_human: Human<Box<dyn Profession>>) -> String {
    any_human.name
}
Run Code Online (Sandbox Code Playgroud)

如果您仍然想要enum,这里有一个建议:将结构放入同名变体中。这样,当您向Profession特征添加行为时,您可以通过推迟内部类型的实现Profession来实现。SomeProfession板条箱enum_derive可以使这个过程变得更容易。

enum SomeProfession {
    Doctor(Doctor),
    Teacher(Teacher),
}

impl Profession for SomeProfession {}

fn into_name_enum(any_human: Human<SomeProfession>) -> String {
    any_human.name
}
Run Code Online (Sandbox Code Playgroud)

也可以看看