我有一个架构,我有一个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 object
与case class
版本类似?
答案 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())
}
如果我错过了一些可以让我结合这两种选择的优雅的东西,我可以接受建议。