在Rust中使用构造的枚举

zc0qhyus  于 2023-05-07  发布在  其他
关注(0)|答案(3)|浏览(184)

我在Java中有一个现有的实现,必须重写为Rust。

Java代码

enum Direction {
    EAST(0), WEST(180), NORTH(90), SOUTH(270);

    private Direction(final int angle) {
        this.angle = angle;
    }

    private int angle;

    public int getAngle() {
        return angle;
    }
}

Java代码使用示例

Direction d1 = Direction.EAST;
Direction d2 = Direction.SOUTH;

Rust代码

我是这么做的

enum Direction {
    East(u32), 
    West(u32), 
    North(u32), 
    South(u32);
}

impl Direction {
    // ???
    fn new() -> Direction // incorrect
}

然后我就被困住了我接下来要做什么?

b09cbbtk

b09cbbtk1#

下面是Java枚举的样子:

+-----+-----+
| tid |   0 |
+-----+-----+
+-----+-----+
| tid |  90 |
+-----+-----+
+-----+-----+
| tid | 180 |
+-----+-----+
+-----+-----+
| tid | 270 |
+-----+-----+

tid对于所有四个方向都是相同的,并且标识类型Direction沿着方法。下面是如何使用Rust代码,East(0)Noth(90)West(180)South(270)看起来像:

+-------+-----+-----+-----+-----+
| East  |   0 |     |     |     |
+-------+-----+-----+-----+-----+
+-------+-----+-----+-----+-----+
| North |     |  90 |     |     |
+-------+-----+-----+-----+-----+
+-------+-----+-----+-----+-----+
| West  |     |     | 180 |     |
+-------+-----+-----+-----+-----+
+-------+-----+-----+-----+-----+
| South |     |     |     | 270 |
+-------+-----+-----+-----+-----+

每个构造函数都有一组不同的字段(在本例中,每个字段一个int)。实际上,由于任何给定的Direction最多是East/North/East/West中的一个,因此在任何时间点都只使用一组字段,并且它们使用相同的内存(因此Direction实际上只占用两个字)。
但从概念上讲,上面的描述是准确的,并说明了Rust版本的两个问题。首先,存在重复:构造器标记(N/E/S/W)对于所有四个已经是不同的,所以int字段是多余的。其次,在概念上,North中的intSouth中的int不同,尽管它们的含义完全相同。此外,没有什么可以阻止创建North(214)East(180)
最直接的翻译是这样的:

enum Direction { North, East, South, West }

impl Direction {
  fn get_angle(self) -> u16 {
    match self {
      Direction::East => 0,
      Direction::West => 180,
      Direction::North => 90,
      Direction::South => 270,
    }
  }
}

方向隐含在enum标记中,并使用get_angle提取。

ljsrvy3e

ljsrvy3e2#

德尔南的答案是绝对正确的,你也许应该接受它,但还有另一种方法。Rust枚举也可以类似于C枚举,其中枚举常量本质上是数字常量。Rust允许你这样写:

enum Direction {
    East = 0,
    North = 90,
    West = 180,
    South = 270
}

然后,你可以使用枚举值作为一个显式转换的数字:

let value = South as uint;
println!("{}", value);  // prints 270

这是因为枚举本质上是具有隐藏鉴别符字段的结构,该字段是一个数字。因此,没有带参数的变量的枚举的值仅包含此鉴别符字段。它的值可以通过数字转换访问,并且您可以在枚举定义中为不同的枚举变量设置具体值。
我的意思是,这只适用于需要整数的情况。你不能像在Java中那样获得字符串或浮点数(在Java中,枚举变量只是带有任意字段的常规对象)。如果你需要它,你必须使用单独的getter方法,就像delnan的答案一样。

neekobn8

neekobn83#

编辑:我不知道Java枚举是关闭的。因此,你也许应该接受德尔南的回答。

我想你想要这样的东西:

pub struct Direction {
    angle: int,
}

impl Direction {
    pub fn new(angle: int) -> Direction {
        Direction {
            angle: angle,
        }
    }

    pub fn get_angle(&self) -> int {
        self.angle
    }
}

pub const EAST: Direction = Direction { angle: 0 };
pub const WEST: Direction = Direction { angle: 180 };
pub const NORTH: Direction = Direction { angle: 90 };
pub const SOUTH: Direction = Direction { angle: 270 };

解释一下:Rust中的enum用于列出不相交变体的有限集合。换句话说,如果Direction只能是EastWestNorthSouth,那么enum就是合适的。

相关问题