实现类工厂最简单的方法?

时间:2016-06-17 22:31:05

标签: rust

我有一个界面:

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
    }
}

在运行时,根据外部条件,我想创建 Derive1Derive2,然后使用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中保留Derive2Main?我应该使用enum还是Box

将来,我可能会Derive3Derive4,所以会很好 减少提到DeriveX的地方数量。

1 个答案:

答案 0 :(得分:4)

您应该使用BoxBox允许您存储trait object,使所有方法调用动态调度。使用enum需要为每个方法实现为每个DeriveXmatch添加新变体。

以下是一个示例(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