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

为了简单起见,设计了以下示例:

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 ,并将 struct 包装在元组 struct 中(正确的术语?)枚举中的每一个都会得到预期的结果,但由于到处都是冗长和相似的类型名,我怀疑我误解了某些东西:

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.

是否在枚举类型(术语?)中包装 struct 同名真的是最好的解决方案吗?Command::Increment(Increment { quantity: 7 })

推荐答案

是的,这是你在这条实施路由上能得到的最好结果.枚举仅为一种类型;它的变体纯粹是那个变体,而不是类型.

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

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>&Command,但这是另一种适合你需求的方式.就定义而言,它更纯粹.

Rust相关问答推荐

如何从Rust记录WASM堆内存使用情况?

防止cargo test 中的竞争条件

如何指定不同的类型来常量Rust中的泛型参数?

如何为rust trait边界指定多种可能性

作为1字节位掩码的布尔值 struct

变量需要parse()中的显式类型

从未排序的链表中删除重复项的铁 rust 代码在ELSE分支的低级上做了什么?

我无法理解Rust范围的定义(Rust Programming Language,第二版克拉布尼克和尼科尔斯)

将Vec<;U8&>转换为Vec<;{Float}&>

根据填充系数以相对大小在给定空间中布局项目

如何迭代存储在 struct 中的字符串向量而不移动它们?

Rust FFI 和 CUDA C 性能差异

Rust 生命周期:这两种类型声明为不同的生命周期

强制特征仅在 Rust 中的给定类型大小上实现

Rust,使用枚举从 HashMap 获取值

Rust,我如何正确释放堆分配的内存?

如何在 C++ 和 Rust 之间共享 pthread 同步原语?

有没有办法隐藏类型定义?

Rust 中的运行时插件

为移动和借位的所有组合实现 Add、Sub、Mul、Div