有没有办法实现阶分层枚举的方法吗?

问题描述 投票:3回答:2

我在我需要的标签接收到的消息的类型项目。消息可以来自不同的来源,但所有这些源产生具有相同的概念类型(因此,相同的含义),但用不同的方式的消息。

例如,从来源1,我可以接受

源1:

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

要么

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

而且从源2我可以接受

源2:

   {
     "message_type": "A", 
     "value": 5 
     ...
   }

要么

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

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

我创建的第一个斯卡拉文件是一个特点:

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并不认为特质作为一个枚举,所以我不能访问枚举值。

你有任何解决方案?

scala enums hierarchy traits enumeration
2个回答
2
投票

是的,你可以做分层枚举。所以一般我会建议不要使用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它不可能是别的(密封/最终因)

这使您可以枚举与全面性检查中模式匹配等。


0
投票

如果“A”和“的typeA”是相同的消息类型的名称,那么你需要的时候,你在数据读取方面来处理这个问题。这意味着,你不需要在你的枚举任何嵌套。

trait MessageType
case object MessageTypeA extends MessageType
case object MessageTypeB extends MessageType

object MessageType {
  def apply(s: String): MessageType =
    s match {
      case "A" | "typeA" => MessageTypeA
      case "B" | "typeB" => MessageTypeB
      case _ => throw BadMessageType
    }
}

case class Message(msgType: MessageType, value: Int)

您可以创建MessageType(<string>)消息类型,它将返回MessageTypeA或适当MessageTypeB。您可以使用正常的match,以确定您有消息类型。


如果您需要保存生成的MessageType原始字符串,那么你可以存储为抽象值在MessageType特质,并创建相应的实例时,填写好:

trait MessageType {
  def origin: String
}

case class MessageTypeA(origin: String) extends MessageType
case class MessageTypeB(origin: String) extends MessageType

object MessageType {
  def apply(s: String): MessageType =
    s match {
      case "A" | "typeA" => MessageTypeA(s)
      case "B" | "typeB" => MessageTypeB(s)
      case _ => throw BadMessageType
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.