Scala Enumerate (枚举)

xiaoxiao2021-02-28  83

Enumerate (枚举)

在Scala中,没有语言级别的枚举类型,枚举的功能可以通过继承枚举类Enumeration实现。

继承枚举类

继承枚举类Enumeration可以在成员中使用无参方法Value给每个枚举成员赋值。 默认的Value方法会按变量名生成枚举名和并自动从0开始生成枚举ID,若需要手动设定枚举名称和枚举ID则可以使用Value方法的重载Value(id: Int, name: Strig)。

如下所示:

object Color extends Enumeration { // 自动赋值枚举成员 val Red, Green, Blue = Value /* * 相当于分别初始化: * val Red = Value * val Green = Value * val Blue = Value */ // 手动使用 Value(id: Int, name: String) 方法手动进行id和name的设置 // 使用重载有參版本的Value(id: Int, name: String)不能一次性给多个枚举成员赋值,会编译报错(id冲突) val White = Value(100, "white") val Black = Value(200, "black") } object TestEnumeration extends App { Color.values foreach { color => println(s"ID: ${color.id}, Str: $color") } }

输出结果:

ID: 0, Str: Red ID: 1, Str: Green ID: 2, Str: Blue ID: 100, Str: white ID: 200, Str: black

Enumeration类的默认构造方法带有一个Int类型参数,用于指定枚举ID的起始大小,如下所示:

object Color extends Enumeration(100) { val Red, Green, Blue, White, Black = Value //枚举Id将从100开始 } object Main extends App { Color.values foreach { color => println(s"ID: ${color.id}, Str: $color") } }

输出结果:

ID: 100, Str: Red ID: 101, Str: Green ID: 102, Str: Blue ID: 103, Str: White ID: 104, Str: Black

访问枚举内容

枚举单例支持以多种形式访问:

通过枚举成员访问,类似于其它常见编程语言(Enum.member)通过枚举ID进行访问,语法类似数组(Enum(id))通过枚举名称进行访问,使用withName成员方法(Enum withName "xxx")

枚举内部的成员全部保存在一个Set容器中,可使用values成员方法访问。

以前文中的Color单例对象为例,使用多种方式访问枚举内容,如下所示:

object Color extends Enumeration { val Red, Green, Blue = Value val White = Value(100, "white") val Black = Value(200, "black") } object Main extends App { def showEnum(color: Color.Value) = println(s"ID: ${color.id}, Str: $color") // 通过枚举ID访问枚举 showEnum(Color(0)) showEnum(Color(100)) println() // 通过枚举名称访问枚举 showEnum(Color withName "Green") showEnum(Color withName "black") println() // 遍历枚举内容 Color.values foreach showEnum }

输出结果:

ID: 0, Str: Red ID: 100, Str: white ID: 1, Str: Green ID: 200, Str: black ID: 0, Str: Red ID: 1, Str: Green ID: 2, Str: Blue ID: 100, Str: white ID: 200, Str: black

调用枚举类型

继承了枚举类的单例对象名并不能直接用于表示枚举类型。 对应的枚举类型应使用对象内部定义的抽象类型Value来表示,即单例对象名称.Value。

以前文中的Color单例对象为例,对应的枚举类型应使用Color.Value表示。 将枚举做为参数传递,如下所示:

object Color extends Enumeration { val Red, Green, Blue = Value val White = Value(100, "white") val Black = Value(200, "black") } object Main extends App { // Xxx.Value才是真正的枚举类型 def showEnum(color: Color.Value) = println(s"ID: ${color.id}, Str: $color") showEnum(Color.blue) showEnum(Color.white) }

输出结果:

ID: 2, Str: Blue ID: 100, Str: white

限定枚举类型

Scala通过使用单例继承Enumeration类来提供枚举功能,枚举值的类型实际为单例.Value。 由于Scala中每个实例的内部类的类型均不相同,需要使用类型投影来表示通用的枚举类型。 枚举值的类型投影为Enumeration#Value。 在泛型方法中,可以使用泛型约束T <: Enumeration#Value来限定泛型参数为枚举类型。 如下所示:

scala> def testEnum[T <: Enumeration#Value](enum: T) = println(enum) //打印枚举参数名称 testEnum: [T <: Enumeration#Value](enum: T)Unit scala> object Enum extends Enumeration { val enum0, enum1 = Value } defined object Enum scala> testEnum(Enum.enum0) //传入枚举类型参数 enum0 scala> testEnum(Enum.enum1) enum1 scala> testEnum(123) //使用其它类型不满足泛型约束,报错 <console>:13: error: inferred type arguments [Int] do not conform to method testEnum's type parameter bounds [T <: Enumeration#Value] testEnum(123) ^ <console>:13: error: type mismatch; found : Int(123) required: T testEnum(123) ^

通过构建特定的枚举基类,可以实现限定指定类别的枚举。 如下所示:

scala> class MyEnumeration extends Enumeration //自定义枚举基类 defined class MyEnumeration scala> def testMyEnum[T <: MyEnumeration#Value](enum: T) = println(enum) //限定枚举从自定义基类MyEnumeration中继承 testMyEnum: [T <: MyEnumeration#Value](enum: T)Unit scala> object Enum extends Enumeration { val enum0, enum1 = Value } //普通枚举 defined object Enum scala> object MyEnum extends MyEnumeration { val enum0, enum1 = Value } //从自定义基类MyEnumeration继承的枚举 defined object MyEnum scala> testMyEnum(MyEnum.enum0) //参数为从自定义枚举基类MyEnumeration继承的枚举单例的枚举值,正常 enum0 scala> testMyEnum(MyEnum.enum1) enum1 scala> testMyEnum(Enum.enum1) //参数为普通枚举单例的枚举值,错误 <console>:14: error: inferred type arguments [Enum.Value] do not conform to method testMyEnum's type parameter bounds [T <: MyEnumeration#Value] testMyEnum(Enum.enum1) ^ <console>:14: error: type mismatch; found : Enum.Value required: T testMyEnum(Enum.enum1) ^
转载请注明原文地址: https://www.6miu.com/read-31681.html

最新回复(0)