我有一个界面:
trait Base {
fn foo(&self) -> i32;
}
及其对两种不同结构的实现:
struct Derive1 {
field1 : u8,
}
struct Derive2 {
field2 : u16,
}
impl Base for Derive1 {
fn foo(&self) -> i32 {
println!("Derive1: {}", self.field1);
self.field1 as i32
}
}
impl Base for Derive2 {
fn foo(&self) -> i32 {
println!("Derive2: {}", self.field2);
self.field2 as i32
}
}
在运行时,根据外部条件,我想创建
Derive1
或Derive2
,然后使用trait
对应的struct
,
我应该用什么来举行struct
?
为了说清楚,例如我有:
struct Main<'a> {
methods: &'a Base
}
impl <'a> Main <'a> {
/*
fn new(external_condition: bool) -> Main<'a> {
}*/
fn call(&self) {
self.methods.foo();
}
}
如何实施Main::new
,以及如何在Derive1
中保留Derive2
或Main
?我应该使用enum
还是Box
?
将来,我可能会Derive3
和Derive4
,所以会很好
减少提到DeriveX
的地方数量。
答案 0 :(得分:4)
您应该使用Box
。 Box
允许您存储trait object,使所有方法调用动态调度。使用enum
需要为每个方法实现为每个DeriveX
和match
添加新变体。
以下是一个示例(Playground):
fn main() {
// 1, 2, .. is decided in runtime
let main = Main::new(1);
main.call();
let main = Main::new(2);
main.call();
}
struct Main {
methods: Box<Base>,
}
impl Main {
fn new(num: usize) -> Main {
let methods: Box<Base> = match num {
1 => Box::new(Derive1 { field1: 1 }),
2 => Box::new(Derive2 { field2: 2 }),
_ => panic!(),
};
Main { methods: methods }
}
fn call(&self) {
self.methods.foo();
}
}
trait Base {
fn foo(&self) -> i32;
}
struct Derive1 {
field1: u8,
}
struct Derive2 {
field2: u16,
}
impl Base for Derive1 {
fn foo(&self) -> i32 {
println!("Derive1: {}", self.field1);
self.field1 as i32
}
}
impl Base for Derive2 {
fn foo(&self) -> i32 {
println!("Derive2: {}", self.field2);
self.field2 as i32
}
}
输出:
Derive1: 1
Derive2: 2