You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala 3带参数枚举为何引发values/valueOf序列化错误?

Scala 3枚举添加带参数Case后values/valueOf不可用的原因

问题场景

正常运行的Scala 3枚举代码

enum BrandSafetyFeatureStatus(val value: Long):
  case Inclusion          extends BrandSafetyFeatureStatus(1L << 0)
  case Exclusion          extends BrandSafetyFeatureStatus(1L << 1)
  case Exception          extends BrandSafetyFeatureStatus(1L << 2)

@main def main(): Unit = {
  println(BrandSafetyFeatureStatus.values)
}

添加带参数Mixed case后的代码

enum BrandSafetyFeatureStatus(val value: Long):
  case Inclusion          extends BrandSafetyFeatureStatus(1L << 0)
  case Exclusion          extends BrandSafetyFeatureStatus(1L << 1)
  case Exception          extends BrandSafetyFeatureStatus(1L << 2)
  private case Mixed(mixed: Long) extends BrandSafetyFeatureStatus(mixed) // ⚠️

  // 位运算方法
  def |(other: BrandSafetyFeatureStatus): BrandSafetyFeatureStatus = Mixed(value | other.value)
  def hasFlag(flag: BrandSafetyFeatureStatus): Boolean = (value & flag.value) == flag.value

@main def main(): Unit = {
  println(BrandSafetyFeatureStatus.valueOf("X")) // 编译失败
  println(BrandSafetyFeatureStatus.values) // 编译失败
}

编译错误信息

value values is not a member of object scala3.BrandSafetyFeatureStatus. Although class BrandSafetyFeatureStatus is an enum, it has non-singleton cases, meaning a values array is not defined

核心疑问

该现象是Scala 3的设计使然,还是未修复的开放Bug?

解答

这是Scala 3的设计特性,而非Bug。

Scala 3对枚举的values数组和valueOf方法有明确生成规则:只有当枚举的所有case都是无参数的单例对象时,编译器才会自动生成这两个成员。一旦枚举中存在带参数的case(比如示例中的Mixed(mixed: Long)),这类case可以创建任意多个实例,枚举不再是“有限固定实例的集合”——此时values无法涵盖所有可能的实例,valueOf也无法通过名称唯一确定实例,因此编译器不会生成这两个成员。

如果需要同时支持位运算混合状态和固定枚举实例的遍历/查找,可以使用enumeratum库实现:

sealed class BrandSafetyFeatureStatus(val value: Long) extends EnumEntry {
  def | (other: BrandSafetyFeatureStatus): BrandSafetyFeatureStatus = BrandSafetyFeatureStatus(value | other.value)
  def hasFlag(flag: BrandSafetyFeatureStatus): Boolean = (value & flag.value) == flag.value
}

object BrandSafetyFeatureStatus extends Enum[BrandSafetyFeatureStatus]:
  case object Inclusion         extends BrandSafetyFeatureStatus(1L << 1)
  case object Exclusion         extends BrandSafetyFeatureStatus(1L << 2)
  case object Exception         extends BrandSafetyFeatureStatus(1L << 3)

  override def values: IndexedSeq[BrandSafetyFeatureStatus] = findValues

@main def main(): Unit = {
  println(BrandSafetyFeatureStatus.withName("X"))
  println(BrandSafetyFeatureStatus.values)
}

enumeratum通过手动定义单例case object并继承EnumEntry,明确区分了固定枚举实例和动态生成的混合状态,同时保留了遍历固定实例的values和查找固定实例的withName方法。

内容的提问来源于stack exchange,提问作者Zvi Mints

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 16:07:10