使用枚举对结构进行分组

时间:2015-03-16 23:17:33

标签: rust

在Rust中,应该如何对相关结构进行分组,以便函数签名在引用方法体内的具体类型时可以接受多种不同的类型?

以下示例是为了简化而设计的:

enum Command {
    Increment {quantity: u32},
    Decrement {quantity: u32},
}

fn process_command(command: Command) {
    match command {
        Command::Increment => increase(command),
        Command::Decrement => decrease(command),
    };
}

fn increase(increment: Command::Increment) {
    println!("Increasing by: {}.", increment.quantity);
}

fn decrease(decrement: Command::Decrement) {
    println!("Decreasing by: {}.", decrement.quantity);
}

fn main() {
    let input = "Add";
    let quantity = 4;

    let command: Command = match input {
        "Add" => Command::Increment { quantity: quantity },
        "Subtract" => Command::Decrement { quantity: quantity },
        _ => unreachable!(),
    };

    process_command(command);
}

在以下两个错误中编译结果:

src/main.rs:13:24: 13:42 error: found value name used as a type: DefVariant(DefId { krate: 0, node: 4 }, DefId { krate: 0, node: 5 }, true) [E0248]
src/main.rs:13 fn increase(increment: Command::Increment) {
                                      ^~~~~~~~~~~~~~~~~~
src/main.rs:17:24: 17:42 error: found value name used as a type: DefVariant(DefId { krate: 0, node: 4 }, DefId { krate: 0, node: 8 }, true) [E0248]
src/main.rs:17 fn decrease(decrement: Command::Decrement) {
                                      ^~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors

如果我单独声明结构,并将结构包装在元组内的元组结构(正确的术语?)中,那么我得到了预期的结果,但是在整个地方都有详细的类似名称我怀疑我我误解了某些事情:

struct Increment {
    quantity: u32,
}

struct Decrement {
    quantity: u32,
}

enum Command {
    Increment(Increment),
    Decrement(Decrement),
}

fn process_command(command: Command) {
    match command {
        Command::Increment(increment) => increase(increment),
        Command::Decrement(decrement) => decrease(decrement),
    };
}

fn increase(increment: Increment) {
    println!("Increasing by: {}.", increment.quantity);
}

fn decrease(decrement: Decrement) {
    println!("Decreasing by: {}.", decrement.quantity);
}

fn main() {
    let input = "Add";
    let quantity = 4;

    let command: Command = match input {
        "Add" => Command::Increment(Increment { quantity: quantity }),
        "Subtract" => Command::Decrement(Decrement { quantity: quantity }),
        _ => unreachable!(),
    };

    process_command(command);
}

运行输出:

Increasing by: 4.

将结构包装在枚举类型(术语?)中,共享同一个名称真的是最好的解决方案吗? Command::Increment(Increment { quantity: 7 })

3 个答案:

答案 0 :(得分:8)

是的,这是您在此实施方案中取得的最佳成绩。枚举只是一种类型;它的变体纯粹是变种,而不是类型。

另一种选择是使用特征和泛型:

struct Increment {
    quantity: u32,
}

struct Decrement {
    quantity: u32,
}

trait Command {
    fn process(self);
}

impl Command for Increment {
    fn process(self) {
        println!("Increasing by {}", self.quantity);
    }
}

impl Command for Decrement {
    fn process(self) {
        println!("Decreasing by {}", self.quantity);
    }
}

当然,它不是直接并行的;如果您要存储command可能不同的类型,则需要更改process以使用self: Box<Self>&self,并且您需要使用Box<Command> {1}}或&Command,但这是另一种可能符合您要求的方式。就定义而言,它更纯粹。

答案 1 :(得分:3)

这个怎么样,我不确定我是否真的理解你的问题

enum Command {
    Increment (u32),
    Decrement (u32),
}

fn process_command(command: Command) {
    match command {
        Command::Increment(quantity) => increase(quantity),
        Command::Decrement(quantity) => decrease(quantity),
    };
}

fn increase(quantity: u32) {
    println!("Increasing by: {}.", quantity);
}

fn decrease(quantity: u32) {
    println!("Decreasing by: {}.", quantity);
}

fn main() {
    let input = "Add";
    let quantity = 4;

    let command: Command = match input {
        "Add" => Command::Increment (quantity),
        "Subtract" => Command::Decrement (quantity),
        _ => unreachable!(),
    };

    process_command(command);
}

答案 2 :(得分:2)

我可能误解了您的简单示例,但请记住,您可以直接在枚举上实现方法:

enum Command {
    Increment {quantity: u32},
    Decrement {quantity: u32},
}

impl Command {
    fn process(self) {
        match self {
            Command::Increment { quantity } => {
                println!("Increasing by: {}.", quantity)
            },
            Command::Decrement { quantity } => {
                println!("Decreasing by: {}.", quantity)
            },
        };
    }
}

fn main() {
    let input = "Add";
    let quantity = 4;

    let command: Command = match input {
        "Add" => Command::Increment { quantity: quantity },
        "Subtract" => Command::Decrement { quantity: quantity },
        _ => unreachable!(),
    };

    command.process();
}

我碰巧喜欢这个版本,因为它消除了process_command(command)的冗余。