首页 > 解决方案 > Scala:使用 Trait + Companion 对象枚举实现

问题描述

我的问题是:这是一个反模式:

我有一个密封的 scala 特征,有十几个或两个实现 - 说这样的话:

package com.erik.logic

sealed trait FailureReason {
  def why: String
}

case object A extends FailureReason {
  val why = "just because"
}
case class B(why: String) extends FailureReason
// ...
case object Z extends FailureReason {
  val why = "idk"
}

导入可能会变得丑陋(或 6 以上,._根据我读过的大多数样式指南开始使用样式)。

一种选择是将它们全部放在特征的伴随对象中,然后我可以以类似于枚举的方式导入和引用它。 这是反模式吗?

package com.erik.logic

trait FailureReason {
  def why: String
}

object FailureReason
  case object A extends FailureReason { ... }
  case class B(why: String) extends FailureReason
  // ...
}

// otherFile.scala
import com.erik.logic.FailureReason

... reason match {
  case FailureReason.A => something
  case FailureReason.B(y) => other(y)
  case FailureReason.C => etc
}


// yetAnotherFile.scala
import com.erik.logic.FailureReason.{A, B, J, Q}

// ... badThing match {
  case SomethingBad => ReasonWrapper(A)
  case SomethingTerrible => ReasonWrapper(B("terrible"))
  case SomethingMeh => ReasonWrapper(Q)
}

标签: scala

解决方案


这不是“反模式”,没关系。您可以顺便说一句,在包级别以相同的方式导入:import com.erik.logic.{A, B, J, Q},因此无需将它们放入对象(但如果您仍然想这样做,它也没有任何问题)。

请注意,您可能应该做出自己的 trait sealedcase这样,如果您忘记了某些子句,您可以利用编译器警告您,并且您match的子句并不详尽。


推荐阅读