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
相关产品推荐
相关产品推荐

