使用case对象来满足抽象类型成员

时间:2014-10-13 00:16:05

标签: scala case-class abstract-type

我有一个架构,我有一个Component的概念,它在运行时从静态配置和/或运行时数据动态实例化。数据的静态部分以Definition类型提供,每个组件必须在其伴随对象中覆盖,以及configurationReads以从JSON反序列化它。

import play.api.libs.json._

trait ComponentDefinition // Intentionally empty

trait ComponentCompanion {
  type Definition <: ComponentDefinition
  def configurationReads: Reads[Definition]
}

对于具有静态选项的组件,我为case class类型提供了Definition

class ParticularComponent { /* blah */ }

object ParticularComponent extends ComponentCompanion {
  case class Definition(option1: String, option2: Boolean) extends ComponentDefinition
  val configurationReads = Json.reads[Definition]
}

这很有效。在过去,我对没有静态选项的组件使用了空case class,但我知道case object会更加惯用。不幸的是,它似乎不起作用。如果我尝试:

class OptionlessComponent { /* blah */ }

object OptionlessComponent extends ComponentCompanion {
  case object Definition extends ComponentDefinition
  val configurationReads = Reads.pure(Definition)
}

我收到以下错误:

<console>:19: error: overriding method configurationReads in trait ComponentCompanion of type => play.api.libs.json.Reads[OptionlessComponent.Definition];
 value configurationReads has incompatible type
             val configurationReads = Reads.pure(Definition)

有没有办法让case objectcase class版本类似?

1 个答案:

答案 0 :(得分:1)

我认为case object在值命名空间中创建了一个新的Definition名称,但没有在类型命名空间中重载抽象type Definition。所以这个编译:

class OptionlessComponent { /* blah */ }

object OptionlessComponent extends ComponentCompanion {
  case object Definition extends ComponentDefinition
  type Definition = Definition.type
  val configurationReads = Reads.pure(Definition)
}

显然,这并不是对空case class版本的无条件胜利:

class OptionlessComponent { /* blah */ }

object OptionlessComponent extends ComponentCompanion {
  case class Definition() extends ComponentDefinition
  val configurationReads = Reads.pure(Definition())
}

如果我错过了一些可以让我结合这两种选择的优雅的东西,我可以接受建议。