Scala扩展Case Object实现可继承枚举状态的方案咨询
核心问题梳理
- 类型继承错误:B、C的伴生对象无需继承A,且你代码中B的apply方法返回值写为C属于明显笔误,编译无法通过
- 子类型不兼容:A中定义的A1、A2是A类型实例,不属于B/C子类型,直接拼接A.vectA到B/C的状态列表中,元素类型会升级为A,无法满足返回B/C类型的要求
- 类型匹配错误:getOrElse返回字符串
"error",和期望返回的枚举类型不匹配,编译直接报错 - 匹配规则不稳定:依赖case object默认的toString做匹配,后续如果修改对象命名会直接导致匹配失效
正确实现方案
下面是Scala原生实现方案,无需引入第三方依赖:
第一步:改造基础父trait
统一状态编码字段,避免依赖默认toString做匹配:
trait A { // 显式定义状态编码,匹配逻辑更稳定 def code: String } object A { // 通用状态定义,此处为def方便子类型复用逻辑 def A1: A = new A { override val code = "A1" } def A2: A = new A { override val code = "A2" } val vectA: Vector[A] = Vector(A1, A2) }
第二步:实现B子类型的枚举和apply方法
单独定义属于B类型的通用状态实例,保证类型合规:
trait B extends A object B { // B自定义扩展状态 case object B1 extends B { override val code = "B1" } case object B2 extends B { override val code = "B2" } // 实现属于B类型的通用状态,保证返回值类型符合要求 case object A1 extends B { override val code = "A1" } case object A2 extends B { override val code = "A2" } // 全量B类型状态列表 private val allStates: Vector[B] = Vector(B1, B2, A1, A2) def apply(status: String): B = allStates.find(_.code == status) .getOrElse(throw new IllegalArgumentException(s"非法B类型状态:$status")) }
第三步:同理实现C子类型
trait C extends A object C { case object C1 extends C { override val code = "C1" } case object C2 extends C { override val code = "C2" } case object A1 extends C { override val code = "A1" } case object A2 extends C { override val code = "A2" } private val allStates: Vector[C] = Vector(C1, C2, A1, A2) def apply(status: String): C = allStates.find(_.code == status) .getOrElse(throw new IllegalArgumentException(s"非法C类型状态:$status")) }
效果验证
调用val x = B("A1")即可得到B类型的实例,完全符合需求。如果不想重复写通用状态的定义,可使用Scala宏或者枚举类库简化重复代码。
内容的提问来源于stack exchange,提问作者Kartik Patel
相关产品推荐
相关产品推荐

