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

Scala中如何重写Enumeration枚举的名称?

解决Scala枚举名称动态重写的问题

Scala标准库的Enumeration中,每个Value实例都是单例,其name属性在构造后就不可修改,且重复使用同一个id创建Value会抛出IllegalArgumentException,所以你直接在运行时创建新Value的方法行不通。下面提供两种可行的实现方案:

方案一:包装原枚举值,自定义显示逻辑

通过创建一个包装类,对原枚举值进行封装,根据冲突情况重写toString方法:

object ErrorCode extends Enumeration {
  type ErrorCode = Value
  
  val UnexpectedError = Value(1, "Unexpected Error")
  val ParamError = Value(2, "Param Error")

  val conflictingValues = Set(UnexpectedError)

  def get(id: Int): Option[ErrorCode.Value] = values.find(_.id == id)

  // 定义包装特质,统一对外接口
  sealed trait ErrorDisplay {
    def id: Int
    override def toString: String
  }

  // 包装原枚举值的实现类
  private case class WrappedError(code: ErrorCode.Value, customName: Option[String] = None) extends ErrorDisplay {
    override def id: Int = code.id
    override def toString: String = customName.getOrElse(code.toString)
  }

  def getErrorWithDifferentName(id: Int): Option[ErrorDisplay] = {
    get(id).map { code =>
      if (conflictingValues.contains(code)) {
        WrappedError(code, Some("Invalid Error"))
      } else {
        WrappedError(code)
      }
    }
  }
}

使用示例:

val err = ErrorCode(1).toString // 输出 "Unexpected Error"
val newErr = ErrorCode.getErrorWithDifferentName(1).get.toString // 输出 "Invalid Error"

方案二:改用sealed trait自定义枚举

放弃Scala标准库的Enumeration,用sealed trait+case object实现枚举,这种方式更灵活,能直接动态生成自定义名称的枚举实例:

sealed trait ErrorCode {
  def id: Int
  def name: String
  override def toString: String = name
}

object ErrorCode {
  case object UnexpectedError extends ErrorCode {
    override val id: Int = 1
    override val name: String = "Unexpected Error"
  }
  case object ParamError extends ErrorCode {
    override val id: Int = 2
    override val name: String = "Param Error"
  }

  val conflictingValues = Set(UnexpectedError)

  def get(id: Int): Option[ErrorCode] = id match {
    case 1 => Some(UnexpectedError)
    case 2 => Some(ParamError)
    case _ => None
  }

  def getErrorWithDifferentName(id: Int): Option[ErrorCode] = {
    get(id).map {
      case err if conflictingValues.contains(err) =>
        // 动态创建自定义名称的ErrorCode实例
        new ErrorCode {
          override val id: Int = err.id
          override val name: String = "Invalid Error"
        }
      case err => err
    }
  }
}

使用示例:

val err = ErrorCode.get(1).get.toString // 输出 "Unexpected Error"
val newErr = ErrorCode.getErrorWithDifferentName(1).get.toString // 输出 "Invalid Error"

两种方案对比:

  • 方案一保留了原Enumeration的结构,适合需要兼容原有代码的场景;
  • 方案二更灵活,是Scala中推荐的枚举实现方式,适合需要自定义行为的场景。

内容的提问来源于stack exchange,提问作者sagar.musale

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:48:35