scala Enumeration with constructor and lookup table 用构造函数和查找表的方式实现的Scala枚举
scala Enumeration with constructor and lookup table 用构造函数和查找表的方式实现的Scala枚举
我在某个地方看到了以下关于枚举的解决方案:
object Day { val values = new ArrayBuffer[Day] case class Day(name:String) { values += this } val MONDAY = new Day("monday") val TUESDAY = new Day("tuesday") }
这个示例展示了我想要实现的内容,但是在ArrayBuffer中有一个隐藏的var变量,有点不好。
我真正想要的是一个val lookupTable = Map(),当有请求时,我可以查找"monday"并将其转换为我的枚举MONDAY,并在整个软件中使用该枚举。通常怎么做呢?我看到了密封特质(sealed traits),但没有看到一种自动确保当有人添加一个继承它的类时,它会自动添加到查找表中的方法。有办法创建一个带有查找表的Scala枚举吗?
Scala的Enumeration似乎接近,因为它有一个values()方法,但我不知道如何传入表示日期的字符串,这是我们从用户那里收到的,然后将其转换为枚举。
谢谢,
Dean
问题的出现原因是希望创建一个具有构造函数和查找表的 Scala 枚举。这种需求可能是因为希望在枚举中添加额外的构造函数参数和方法。
解决方法是使用 Scala 的 Enumeration 类,并通过创建一个继承 Enumeration.Val 的 sealed case class 来实现具有构造函数的枚举。
下面是解决方法的示例代码:
object Currency extends Enumeration { sealed case class CurrencyVal(name: String, value: Int) extends Val(name) { def *(n: Int): Int = n * value } val PENNY = CurrencyVal("penny", 1) val NICKLE = CurrencyVal("nickle", 5) val DIME = CurrencyVal("dime", 10) val QUARTER = CurrencyVal("quarter", 25) override def withName(name: String): CurrencyVal = { super.withName(name).asInstanceOf[CurrencyVal] } }
在上述代码中,CurrencyVal 是一个带有额外构造函数参数的 sealed case class,它继承自 Enumeration.Val。在 Currency 对象中,我们定义了几个具体的 CurrencyVal 实例,每个实例都具有不同的名称和值。
通过重写 withName 方法,我们可以确保调用 withName 方法时返回的是 CurrencyVal 而不是默认的 Currency.Value。
通过这种方式,我们可以实现具有构造函数和查找表的 Scala 枚举。这种枚举可以包含多个参数,例如整数代码、toString 版本等。
这样的解决方案可以满足需要将代码映射到枚举的情况,并且在枚举中添加更多的构造函数参数和方法时也能正常工作。同时,这种解决方案还能够防止枚举值被重命名时出现问题。
问题的出现原因是作者想要创建一个Scala枚举(enum)并希望能够自动地将新添加的子类添加到查找表(lookup table)中。作者提到了他之前看到过密封特质(sealed traits),但没有找到一种自动将扩展该特质的子类添加到查找表中的方法。
为了解决这个问题,作者介绍了一个名为Enumeratum的小型库。使用该库的方法如下:
import enumeratum._ sealed abstract class Day(val entryName: String) extends EnumEntry case object Day extends Enum[Day] { val values = findValues case object MONDAY extends Day("monday") case object TUESDAY extends Day("tuesday") // etc } Day.withName("monday") // 返回 MONDAY
这段代码中,首先引入了`enumeratum`库。然后定义了一个名为`Day`的密封抽象类,该类有一个名为`entryName`的参数。`Day`对象继承了`Enum[Day]`,并且定义了一个`values`值,该值会在编译时自动将声明的子类添加到一个映射表中。在子类中,每个具体的枚举值都有一个对应的`entryName`值。
通过调用`Day.withName("monday")`方法,可以返回对应的枚举值`MONDAY`。
通过使用Enumeratum库,作者成功解决了创建Scala枚举并自动添加子类到查找表的问题。