Scala - 枚举与案例类

13 enums scala case-class actor akka

我创建了一个名为LogActor的akka​​ actor.LogActors的receive方法处理来自其他actor的消息并将它们记录到指定的日志级别.

我可以通过两种方式区分不同的关卡.第一个:

import LogLevel._
object LogLevel extends Enumeration {
    type LogLevel = Value
    val Error, Warning, Info, Debug = Value
}
case class LogMessage(level : LogLevel, msg : String) 
Run Code Online (Sandbox Code Playgroud)

第二个:( 编辑)

abstract class LogMessage(msg : String)
case class LogMessageError(msg : String) extends LogMessage(msg)
case class LogMessageWarning(msg : String) extends LogMessage(msg)
case class LogMessageInfo(msg : String) extends LogMessage(msg)
case class LogMessageDebug(msg : String) extends LogMessage(msg)
Run Code Online (Sandbox Code Playgroud)

哪种方式更有效?是否需要更少的时间来匹配案例类或匹配枚举值?

(我读过这个问题,但没有任何答案提到运行时问题)

Nik*_*kov 27

我完全同意Alexey和Dennis在这种情况下的性能不应该打扰你,因为它更多的是编译器优化的问题,而不是开发人员,我无法想象性能差异可能变得明显的情况.

应该打扰你的是你的代码一致性,从这个意义上讲,你应该根据你的第一个例子中正确描述的枚举或者最近增长的流行代数数据类型来坚持使用旧的java-ish方法做出决定.(ADT)模式.后者你试图在你的第二个例子中代表,但有一些错误.

以下是如何正确解决ADT模式的问题.

ADT解决方案#1

// 1. marked `sealed` to make pattern matching exhaustive
// 2. used a trait to avoid double storage of msg` and 
//    make the inheritance easier
sealed trait LogMessage { def msg : String }
// A better solution for isolation than names like "LogMessageError".
// Allows you to either address the members with a namespace like 
// "LogMessage.Error" or do "import LogMessage._" and address them 
// directly
object LogMessage { 
  case class Error (msg : String) extends LogMessage
  case class Warning (msg : String) extends LogMessage
  case class Info (msg : String) extends LogMessage
  case class Debug (msg : String) extends LogMessage
}
Run Code Online (Sandbox Code Playgroud)

ADT解决方案#2

很抱歉可能会弄乱你的脑袋,但值得注意的是,对于类似的情况也存在替代的ADT方法,这类似于你用枚举的方式.

sealed trait LogLevel 
object LogLevel {
  case object Error extends LogLevel
  case object Warning extends LogLevel
  case object Info extends LogLevel
  case object Debug extends LogLevel
}
case class LogMessage ( level : LogLevel, msg : String )
Run Code Online (Sandbox Code Playgroud)


Ale*_*nov 8

"不要过早优化"适用.我不相信它们之间的差异可能很重要,相比之下,您花费时间将消息传递给您的演员或实际记录它们.但我希望最好的表现是创建一个Java enum(可以从Scala轻松访问和使用)来记录级别而不是Scala Enumeration.