【问题标题】:Enums with constructions in RustRust 中带有结构的枚举
【发布时间】:2015-01-12 19:10:29
【问题描述】:

我有现有的 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;

锈代码

这就是我尝试过的:

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

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

然后我就卡住了。接下来我该怎么做?

【问题讨论】:

    标签: enums rust


    【解决方案1】:

    您的 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) -> int {
        match self {
          East => 0,
          West => 180,
          North => 90,
          South => 270,
        }
      }
    }
    

    方向隐含在枚举标签中,用get_angle提取。

    【讨论】:

      【解决方案2】:

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

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

      然后您可以将枚举值用作具有显式强制转换的数字:

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

      这是可行的,因为枚举本质上是具有隐藏鉴别器字段的结构,该字段是一个数字。因此,没有变体的枚举值仅包含此鉴别器字段。它的值可以通过数字转换来访问,您可以在枚举定义中为不同的枚举变量设置具体值。

      我的意思是,这仅在您需要整数时才有效。你不能以这种方式获取字符串或浮点数,就像在 Java 中那样(枚举变体只是具有任意字段的常规对象)。如果你需要它,你将不得不使用单独的 getter 方法,就像在 delnan 的回答中一样。

      【讨论】:

        【解决方案3】:

        编辑:我不知道 Java 枚举已关闭。因此,您可能应该选择 delnan 的答案。

        我想你想要这样的东西:

        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 将是合适的。

        【讨论】:

        • JavaDirection也只能是E/W/N/S,不能是任意角度。
        • 啊,好的。我以前从未在 Java 中使用过枚举。
        猜你喜欢
        • 2023-01-03
        • 1970-01-01
        • 2017-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-10
        • 2019-02-07
        相关资源
        最近更新 更多