scala - 有没有办法在 Scala 中实现分层枚举?

标签 scala enums hierarchy traits enumeration

我正在一个项目中工作,我需要在其中标记收到的消息的类型。消息可以来自不同的来源,但所有这些来源都生成具有相同概念类型(因此,相同含义)但以不同方式编写的消息。

例如从 source1 我可以收到

来源1:

    {
     "message_type": "typeA",
     "value": 3 
     ...
    }

或者
    {
     "message_type": "typeB",
     "value": 3 
     ...
    }

但也从 source2 我可以收到

来源2:
   {
     "message_type": "A", 
     "value": 5 
     ...
   }

或者
    {
     "message_type": "B",
     "value": 2 
     ...
    }

我想最大化代码重用,所以我尝试了这个解决方案。

我创建的第一个 Scala 文件是一个特征:
trait MessageType extends Enumeration {
    val TYPE_A: Value
    val TYPE_B: Value
}

然后我在两个目标文件中实现了它:
object Source1MessageType extends MessageType{
    override val TYPE_A: Value("typeA")
    override val TYPE_B: Value("typeB")

object Source2MessageType extends MessageType{
    override val TYPE_A: Value("A")
    override val TYPE_B: Value("B")

所以现在我想要的是在不知道源类型的情况下检查消息的类型,如下所示:
def foo(type: MessageType.Value) {
    type match{
        case MessageType.TYPE_A => ...do A action...
        case MessageType.TYPE_B => ...do B action...
    }
}

但是,如果我编写此代码,IDE (IntelliJ) 会以红色突出显示该参数,但不会提供有关错误的任何信息。似乎我只能使用 Source1MessageType 或 Source2MessageType 作为参数类型。

我认为错误是因为 Scala 没有将特征视为枚举,所以我无法访问枚举的值。

你有什么解决办法吗?

最佳答案

是的,您可以进行分层枚举。所以一般我会建议不要使用 Enumeration .这是一篇关于为什么不好的文章

https://medium.com/@yuriigorbylov/scala-enumerations-hell-5bdba2c1216

最惯用的方法是利用这样的密封特性:

sealed trait MessageType{
  def value:String
}
sealed trait MessageType1 extends MessageType
final case object TypeA extends MessageType1{
   override def value:String = "typeA"
}
final case object TypeB extends MessageType1{
   override def value:String = "typeB"
}
sealed trait MessageType2 extends MessageType
final case object A extends MessageType2{
   override def value:String = "A"
}
final case object B extends MessageType2{
   override def value:String = "B"
}

请注意,所有这些定义都需要在同一个文件中。现在这有效,因为 sealedfinal告诉编译器继承只能发生在这个文件中。

这意味着给定一个 MessageType2 的实例编译器知道它只能是对象 AB它不能是其他任何东西(因为密封/最终)

这为您提供了模式匹配等方面的详尽检查的枚举。

关于scala - 有没有办法在 Scala 中实现分层枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54589703/

相关文章:

php - 具有父子关系的不同表的访问控制

JAVA类层次结构: Which of the following lines will not compile?

ssas - 引用相同属性的不平衡层次结构

scala - 使用密封特征作为 map 的键

scala - 如何表达 Scala 的 Try 的 *finally* 等价物?

java - 将对象的值与枚举的值进行比较

c++ - 在 C++ 中使用枚举作为模板类型参数

scala - 如何向仿函数映射函数添加类型约束

scala - 使用 LIKE 子句对查询进行异常过滤

c - 从 C 项目中提取所有枚举的最佳方法