Scala 枚举的使用和探索(译)

【Scala面向对象】35、Enumeration枚举类 在 Scala 中,没有像 Java 那样原生的枚举类型,但是可以通过EnumName是枚举类的名称,通常按照 Scala 的命名规范使用首字母大写的形式。是 Scala 内置的枚举类对象,用于定义枚举成员。是枚举类的成员,用于表示一组常量值。每个枚举成员都是Value的实例。每个枚举成员默认的值是Value的实例,其顺序由定义的顺序决定,从 0 开始。在上述示例中,我们为枚举成员和分别指定了值 1、2 和 3。在使用枚举类时,可以通过。 阅读详情

Scala 枚举示例和特性

枚举(Enumerations)是一种语言特性,对于建模有限的实体集来说特别有用。一个经典的例子是将工作日建模为一个枚举:每个七天都有一个值。Scala和许多其他语言一样,提供了一种表示枚举的方法:

object Weekday extends Enumeration {
  val Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday = Value
}

现在我们可以准确清晰地表示工作日,而无需使用String或Int等基本类型。Scala枚举还提供了一组有用的特性:

  • 序列化和反序列化方法(Serialize and Deserialize methods),这些方法也会抛出异常:(:
scala> Weekday.Monday.toString
res0: String = Monday

scala> Weekday.withName("Monday")
res1: Weekday.Value = Monday

scala> Weekday.withName("Mondai")
java.util.NoSuchElementException: No value found for 'Mondai'
  at scala.Enumeration.withName(Enumeration.scala:124)
  ... 32 elided
  • 提供可读性(human-readable value)的值:
object Weekday extends Enumeration {
    val Monday = Value("Mo.")
    val Tuesday = Value("Tu.")
    val Wednesday = Value("We.")
    val Thursday = Value("Th.")
    val Friday = Value("Fr.")
    val Saturday = Value("Sa.")
    val Sunday = Value("Su.")
  }

scala> Weekday.Monday.toString
res0: String = Mo.
  • 列出所有可能的值:
scala> Weekday.values
res0: Weekday.ValueSet = Weekday.ValueSet(Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)
  • 排序(Ordering)。默认情况下,枚举值是按照声明的顺序排序的,排序顺序可以通过覆盖(overridden)原来枚举值的方式改变:
object Weekday extends Enumeration {
  val Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday = Value
}

// 按照枚举值声明的顺序排序
scala> Weekday.values.toList.sorted
res0: List[Weekday.Value] = List(Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)
object Weekday extends Enumeration {
  val Monday = Value(1)
  val Tuesday = Value(2)
  val Wednesday = Value(3)
  val Thursday = Value(4)
  val Friday = Value(5)
  val Saturday = Value(6)
  val Sunday = Value(0)
}

// 按照枚举对应的数字值排序
scala> Weekday.values.toList.sorted
res1: List[Weekday.Value] = List(Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday)

scala.Enumeration的问题

然而,这种方法有一些问题。主要有两个缺点:

  • 擦除(erasure)后枚举具有相同的类型:
object Weekday extends Enumeration {
    val Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday = Value
}

object OtherEnum extends Enumeration {
	val A, B, C = Value
}

def test(enum: Weekday.Value) = {
    println(s"enum: $enum")
}

def test(enum: OtherEnum.Value) = {
    println(s"enum: $enum")
}

<console>:25: error: double definition:
def test(enum: Weekday.Value): Unit at line 21 and
def test(enum: OtherEnum.Value): Unit at line 25
have same type after erasure: (enum: Enumeration#Value)Unit
         def test(enum: OtherEnum.Value) = {
             ^
  • 在编译期间没有详尽的匹配检查(matching check)。下面的示例将在没有任何警告的情况下编译,但是在对周一和周日以外的工作日匹配时会抛出scala.MatchError异常:
def nonExhaustive(weekday: Weekday.Value) {
  weekday match {
    case Monday => println("I hate Mondays")
    case Sunday => println("The weekend is already over? :( ")
  }
}

在Scala中,我们严重依赖于编译器强大的类型系统,使用这种方法,编译器不能找到非穷尽模式匹配子句,也不能对不同的枚举使用重载方法。

为了避免这种问题,我们可以其他办法实现枚举:

  • 使用密封盒对象(sealed case objects)
  • 分项(itemized)
  • enumeratum

Sealed case objects

如果您决定使用sealed case objects,Scala编译器可以解决Scala枚举中存在的两个问题。编译器既可以检测非穷尽模式匹配,也可以避免类型擦除问题。

sealed trait Weekday

case object Monday extends Weekday
case object Tuesday extends Weekday
case object Wednesday extends Weekday
case object Thursday extends Weekday
case object Friday extends Weekday
case object Saturday extends Weekday
case object Sunday extends Weekday

def test(weekday: Weekday) = {
    weekday match {
      case Monday => println("I hate Mondays")
      case Sunday => println("The weekend is already over? :( ")
    }
}

<console>:15: warning: match may not be exhaustive.
It would fail on the following inputs: Friday, Saturday, Thursday, Tuesday, Wednesday
           weekday match {
           ^
test: (weekday: Weekday)Unit

另一个非常好的特性是,可以在枚举值中包含更多字段(Scala enumerations only provides an index and a name),仅仅使用sealed abstract class而不是sealed trait。

sealed abstract class Weekday( val name: String,
                               val abbreviation: String,
                               val isWorkDay: Boolean)

case object Monday extends Weekday("Monday", "Mo.", true)
case object Tuesday extends Weekday("Tuesday", "Tu.", true)
case object Wednesday extends Weekday("Wednesday", "We.", true)
case object Thursday extends Weekday("Thursday", "Th.", true)
case object Friday extends Weekday("Friday", "Fr.", true)
case object Saturday extends Weekday("Saturday", "Sa.", false)
case object Sunday extends Weekday("Sunday", "Su.", false)

sealed case objects的问题

但是这种方式也有它自己的问题:

  • 没有检索所有枚举值的简单方法
  • 没有默认的序列化/反序列化方法
  • 枚举值之间没有默认的排序——这可以通过包含一些关于值的信息来手动实现,示例如下:
sealed abstract class Weekday( val name: String,
                               val abbreviation: String,
                               val isWeekDay: Boolean,
                               val order: Int) extends Ordered[Weekday] {

  def compare(that: Weekday) = this.order - that.order
}

case object Monday extends Weekday("Monday", "Mo.", true, 2)
case object Tuesday extends Weekday("Tuesday", "Tu.", true, 3)
case object Wednesday extends Weekday("Wednesday", "We.", true, 4)
case object Thursday extends Weekday("Thursday", "Th.", true, 5)
case object Friday extends Weekday("Friday", "Fr.", true, 6)
case object Saturday extends Weekday("Saturday", "Sa.", false, 7)
case object Sunday extends Weekday("Sunday", "Su.", false, 1)

scala> Monday < Tuesday
res0: Boolean = true

分项(itemized)

itemized是一个OSS lib,它是rbrick的一部分,rbricks是一种可组合的、占用空间小的Scala库的集合。

itemized为枚举提供了密封特质层次结构(sealed trait hierarchies)的宏和类型类,回到我们之前的例子:

import io.rbricks.itemized.annotation.enum

@enum trait Weekday {
  object Monday
  object Tuesday
  object Wednesday
  object Thursday
  object Friday
  object Saturday
  object Sunday
}

除上面的以外,itemized还有其他的一些特性:

  • 列出所有枚举值
  • 默认的序列化/反序列化方法
scala> import io.rbricks.itemized.ItemizedCodec

scala> ItemizedCodec[Weekday].fromRep("Monday")
res0: Option[Weekday] = Some(Monday)

scala> val weekday: Weekday = Planet.Monday

scala> import io.rbricks.itemized.ItemizedCodec.ops._

scala> weekday.toRep
res1: String = Earth

itemized的问题

尽管itemized可以让我们用注解方式创建类型安全的枚举,但是它也有一些不足:

enumeratum

Enumeratum是一个类型安全且功能强大的Scala枚举实现,它提供了详尽的模式匹配警告。

import enumeratum._

sealed trait Weekday extends EnumEntry
object Weekday extends Enum[Weekday] {
  val values = findValues // mandatory due to Enum extension

  case object Monday extends Weekday
  case object Tuesday extends Weekday
  case object Wednesday extends Weekday
  case object Thursday extends Weekday
  case object Friday extends Weekday
  case object Saturday extends Weekday
  case object Sunday extends Weekday
}
def test(weekday: Weekday) = {
    weekday match {
      case Weekday.Monday => println("I hate Mondays")
      case Weekday.Sunday => println("The weekend is already over? :( ")
    }
  }

<console>:18: warning: match may not be exhaustive.
It would fail on the following inputs: Friday, Saturday, Thursday, Tuesday, Wednesday
           weekday match {
           ^
test: (weekday: Weekday)Unit

除了非详尽的模式匹配警告,enumeratum还提供:

  • 列出可能的值(因为这些值需要在Enum继承上实现)
  • 默认的序列化/反序列化方法(有和没有异常抛出)
scala> Weekday.withName("Monday")
res0: Weekday = Monday

scala> Weekday.withName("Momday")
java.util.NoSuchElementException: Momday is not a member of Enum (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)
  at enumeratum.Enum$$anonfun$withName$1.apply(Enum.scala:82)
  at enumeratum.Enum$$anonfun$withName$1.apply(Enum.scala:82)
  at scala.Option.getOrElse(Option.scala:121)
  at enumeratum.Enum$class.withName(Enum.scala:81)
  at Weekday$.withName(<console>:13)
  ... 43 elided

scala> Weekday.withNameOption("Monday")
res2: Option[Weekday] = Some(Monday)

scala> Weekday.withNameOption("Momday")
res3: Option[Weekday] = None
  • 向枚举添加额外的值。它非常类似于我们给简单的密封盒对象添加额外的值
sealed abstract class Weekday( val name: String,
                               val abbreviation: String,
                               val isWorkDay: Boolean) extends EnumEntry

case object Weekday extends Enum[Weekday] {
  val values = findValues
  case object Monday extends Weekday("Monday", "Mo.", true)
  case object Tuesday extends Weekday("Tuesday", "Tu.", true)
  case object Wednesday extends Weekday("Wednesday", "We.", true)
  case object Thursday extends Weekday("Thursday", "Th.", true)
  case object Friday extends Weekday("Friday", "Fr.", true)
  case object Saturday extends Weekday("Saturday", "Sa.", false)
  case object Sunday extends Weekday("Sunday", "Su.", false)
}
  • 排序可以通过与封闭层次(sealed hierarchies)结构相同的方式实现。只需与有序[]特质(trait)混合,并实现比较方法。
sealed abstract class Weekday(val order: Int) extends EnumEntry with Ordered[Weekday] {
   def compare(that: Weekday) = this.order - that.order
 }

 object Weekday extends Enum[Weekday] {
   val values = findValues

   case object Monday extends Weekday(2)
   case object Tuesday extends Weekday(3)
   case object Wednesday extends Weekday(4)
   case object Thursday extends Weekday(5)
   case object Friday extends Weekday(6)
   case object Saturday extends Weekday(7)
   case object Sunday extends Weekday(1)
 }

总结

如果您刚刚开始学习Scala,我建议使用scala.Enumeration的方式实现枚举。当您觉得使用更多Scala特性更舒服时,以及开始享受编译器安全性时,可以试试其他方式实现枚举。我的两个建议是:

  • 如果您不想依赖于外部库,就使用sealed hierarchies
  • 使用enumeratum,因为它提供了这里提到的所有特性

枚举特性总结

  • 详尽的模式匹配
  • 没有类型擦除
  • 安全的序列化/反序列化的默认方法
  • 列出所有可能的值
  • 在枚举值上添加额外的字段
  • 排序

如果您想看到更多的替代方法,请查看Scala枚举的后续内容—Scala Enumerations - Return of the (Java) Jedi

编译自:Scala Enumerations

STM32实现4-20mA压控恒流源电路设计与调试实战 在工业控制与仪器仪表领域,模拟量输出常以电流环信号传输,其中4-20mA电流标准因抗干扰能力强、传输距离远而成为主流。其4mA下限不仅能为两线制变送器供电,还预留了断线检测空间,对工业安全意义重大。实现该输出通常采用DAC配合压控恒流源电路,相比PWM滤波方案,DAC输出更稳定、分辨率更高,能有效降低输出纹波。此类电路广泛用于阀门开度控制、变频器给定及变送器信号驱动等场景,是连接数字控制器与现场执行器的关键接口。文章从恒流源工作原理出发,详细拆解基于运放和晶体管的V-I变换电路,并给出STM32的DAC配置 阅读详情

相关推荐

scala-enum:基于密封类的 Scala 枚举的简单 40 行实现

标量枚举 这是基于密封类(支持模式匹配耗尽检查)的枚举的简单 40 行实现。 它使用反射,因此如果您使用它,您可能需要将libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaV到您的项目中。 对象的枚举 定义 sealed abstract class Color ( red : Double , green : Double , blue : Double ) object Color extends EnumOf [ Color ] { case object Red extends Color ( 1 , 0 , 0 ) case object Green extends Color ( 0 , 1 , 0 ) case object Blue extends Color ( 0 , 0

scala中的枚举

1.scala枚举原理 严格来说,和其它语言不同,Scala 并没有枚举这种类型。Scala 中的枚举值只是Enumeration下的Value类的实例,而不是枚举自身的实例。Value类的实例主要依靠其构造方法的两个值:id与name来构建。其中,id是自增长,name如果不指定时默认使用的就是值的名字。所以不像其它语言,Scala 并不能任意定义构造方法来构造枚举。 abstract clas...

bitcarmanlee的博客 3581

Hermes Dashboard Web 端部署完整说明

通过反向代理(nginx)使用公网域名访问时,会遇到 Host 头校验、CORS 跨域、WebSocket 连接拒绝三个核心问题。本文档记录了完整的源码修改方案和部署步骤。确保 nginx 主配置加载了 WebSocket map(宝塔默认为。路径的公开访问(无需登录),其他路径仍受 Cookie 认证保护。Hermes Dashboard 默认绑定。访问站点时会先弹出浏览器密码框,输入用户。在 nginx 反向代理配置中的。环境变量动态读取允许的域名。nginx 配置中已添加。

大白菜代码的博客 805

Scala 中的枚举

在源码的Example中可以看到所有的枚举都是被赋值为Value类型,从上面的源码中可以看到Value类是一个抽象类,看它的内容只是提供了枚举值比较以及id的获取,在Enumeration源码中提供了一个叫Val的类对Value实现,重要是重写了整数命名和id的识别。请注意,请注意,Example中的第4行、第5行的Value,前者是类,后者是方法(括号省略了而已)上面提供了各种Value的重载方法均是返回了Val类,所以说嘛,你有需要完全可以自己再实现一个Value类。

Code_LT的博客 611

QuecOpen RTOS学习笔记

对计算机响应时间有要求的系统,通常称为临界系统或应用。为了满足临界系统或应用对计算机响应 时间的要求,人们开发了实时操作系统(Real Time Operation System)。 实时操作系统指所有任务均在规定时间内完成的操作系统,同时任务完成必须满足时序可预测性。需 要注意的是,实时操作系统的本质是其反应具有时序可预测性。得益于此,实时操作系统通常反应非常快。 实时操作系统的内核对象一般包括任务、信号量、互斥锁、消息队列、定时器、事件通知和软件看门 狗等。

zxm8513优快云博客 2030

LCZ数据下载及处理-以重庆市为例(完整Python代码)

LCZ数据下载及处理-以重庆市为例(完整Python代码)

WW、forever的博客 611

枚举scala

case d if d == Stars.地球 || d == Stars.火星 => println(s"适合人类居住的星球 = $d")val 地球 = Value(-1, "地球是最美丽的蔚蓝色")val 火星 = Value(4, "火星是火红颜色的")val 金星 = Value(0, "金星是金色的")val 地球 = Value("地球是最美丽的蔚蓝色")val 火星 = Value("火星是火红颜色的")val 金星 = Value("金星是金色的")

2403_87257611的博客 540

二十一、SAP-库存管理

业务逻辑、功能讲解、图文解析、章节总结

m0_72403327的博客 1810

Scala里面如何使用枚举

枚举通常用来定义已知数量的常量,比如月份,星期,季节等等,用过java的人都知道定义枚举的关键字是enum,在scala里面和java有所不同,来看一个完整的例子定义: object EnumTest { /*** * 定义一个星期的枚举 */ object WeekDay extends Enumeration{ type WeekDay = Value ...

qq_32253371的博客 301

DeepSeek Harness“一切皆插件”核心机制详解

DeepSeek Harness 的“一切皆插件”核心 = Cordis 微内核 + 服务化能力接口 + 声明式依赖注入 + 类型化事件 + 可逆副作用 + 配置层 Profile/Bundle/Patch 组合。它的工程收益是:把模型、工具、循环、存储、UI 等所有 Agent 能力都变成“可从配置替换、可干净装卸”的单元,而不是写死在框架里。

软件行业技术文化交流。 600

Python 爬虫实战:解析 JSON 数据爬取今日头条热点新闻(API 接口逆向与字段提取)

在当今信息爆炸的时代,新闻资讯的获取变得尤为重要。今日头条作为国内领先的新闻聚合平台,其热点新闻数据具有很高的价值。本文将详细介绍如何通过 Python 爬虫技术,逆向解析今日头条的 API 接口,提取并解析 JSON 数据,最终获取热点新闻信息。

yansideyucsdn的博客 3210

Scala Enumerate (枚举)

Enumerate (枚举)在Scala中,没有语言级别的枚举类型,枚举的功能可以通过继承枚举类Enumeration实现。继承枚举类继承枚举类Enumeration可以在成员中使用无参方法Value给每个枚举成员赋值。

言の叶の庭 6233

80、编程学习资源与x86知识全解析

本文详细介绍了编程学习中多个领域的优秀书籍和博客资源,涵盖逆向工程、C/C++、x86/x86-64架构、ARM、汇编语言、Java、UNIX、密码学等多个方向。同时,深入解析了x86架构的核心知识,包括术语、通用寄存器、FPU寄存器、SIMD寄存器、调试寄存器以及常用指令的使用方法和操作步骤。通过本文,读者可以系统地掌握底层编程知识,并应用于逆向工程、系统开发和性能优化等领域。

tree的博客 221

Scala枚举

Scala定义枚举类,需要扩展类对象为scala.Enumeration。 定义 // 1 object DeployMode extends Enumeration { val LOCAL,TEST,PRODUCTION = Value } // 2 object DeployMode extends Enumeration { val LOCAL = Value v...

L, there! 448

Android功耗系列专题分析之四:待机概率性功耗高的失效分析

本文分析了Android设备待机功耗异常高的问题。通过日志发现系统休眠失败,原因是PowerManagerService.Display唤醒锁未被释放。进一步排查发现,指纹解锁功能在灭屏时未正确释放屏幕锁定,导致DisplayReady状态异常。解决方案是将指纹功能的背光控制与DisplayReady状态控制分离,使用两个变量独立管理。经验表明,快速定位问题比解决问题更重要,修改原生流程时需谨慎评估风险。

451

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

scala 中的枚举类型

Scala中的枚举 枚举在编程中指的是命名的常量,在scala中提供了一个Enumeration类,我们可以扩展它以创建枚举。 在scala中声明枚举 object Main extends Enumeration { type Main = Value // 赋值 val first = Value("惊悚片") val second = Value("恐怖片") va...

wangrui1605的博客 1563

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

java调用scala枚举_Scala里面如何使用枚举

枚举通常用来定义已知数量的常量,比如月份,星期,季节等等,用过java的人都知道定义枚举的关键字是enum,在scala里面和java有所不同,来看一个完整的例子定义:object EnumTest {/**** 定义一个星期的枚举*/object WeekDay extends Enumeration{type WeekDay = Value //声明枚举对外暴露的变量类型val Mon = ...

weixin_32296621的博客 293

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

判断字段是否与枚举相同_Scala基础学习九之枚举和Trait了解

scala枚举枚举:Scala不支持enum关键字,通过继承Enumeration类实现枚举枚举通常用来定义已知数量的常量,比如月份,星期,季节等等定义一个星期的枚举并定义一个打印所有值的方法我们调用运行看一下,直接打印的枚举中的变量值打印语句可以简化调用我们看输出的值可以直接调用枚举值withName也可以直接获取有一个id 的属性toString直接通过下标如果我们改变Tue的值,查看id的变...

weixin_39521520的博客 289

[Scala基础]--Scala枚举使用

参考:http://www.scala-lang.org/api/current/scala/Enumeration.htmlhttp://www.jianshu.com/p/675dad38c8a6http://xiaoxin2009.github.io/Scala%E7%B1%BB%EF%BC%8C%E5%AF%B9%E8%B1%A1.htmlScala的枚举与java/c++不同,scala...

欢迎来到我的博客,一起探索代码里的世界! 2647

scala中 object 和 class的区别

object class 区别: 联系:

节至 6万+

枚举类型enum用法_Scala基础学习九之枚举和Trait了解

scala枚举枚举:Scala不支持enum关键字,通过继承Enumeration类实现枚举枚举通常用来定义已知数量的常量,比如月份,星期,季节等等定义一个星期的枚举并定义一个打印所有值的方法我们调用运行看一下,直接打印的枚举中的变量值打印语句可以简化调用我们看输出的值可以直接调用枚举值withName也可以直接获取有一个id 的属性toString直接通过下标如果我们改变Tue的值,查看id的变...

weixin_39628063的博客 269

scala case class 继承_Scala学习九之枚举和Trait了解

scala枚举枚举:Scala不支持enum关键字,通过继承Enumeration类实现枚举枚举通常用来定义已知数量的常量,比如月份,星期,季节等等定义一个星期的枚举并定义一个打印所有值的方法我们调用运行看一下,直接打印的枚举中的变量值打印语句可以简化调用我们看输出的值可以直接调用枚举值withName也可以直接获取有一个id 的属性toString直接通过下标如果我们改变Tue的值,查看id的变...

weixin_39629947的博客 241

Scala 定义复杂枚举

通常我们需要枚举参数不止两个,Scala提供的枚举类最多定义两个参数:id:Int与name:String。不能满足我们通常要求。 1 object BaseEntryEnum extends Enumeration { 2 type BaseEntryEnum = Value 3 //item_base类别 4 val ITEM_TYPE_PURCHASE_CENTER ...

weixin_30670925的博客 482

java调用scala枚举_Scala中的枚举

与java不同,scala并没有提供枚举类型,而是通过Enumeration类的帮助来实现枚举功能的。object SourceType extends Enumeration{//这行是可选的,类型别名,在使用import语句的时候比较方便,建议加上type SourceType = Value//枚举的定义val Kafka, Avro, Custom = Value}使用方法def load...

weixin_28973031的博客 317
上一篇: Consumer is not subscribed to any topics
下一篇: Spring Cloud自动推送配置到Consul配置中心
Viking_bird
博客等级 码龄11年 92粉丝 183原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值