请看一下代码:
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 不断发展,其次,我要求一种解决方法。
也许最简单的事情就是创建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)