让我们建立一些背景。 Data
由Metadata
和Payload
组成。
trait Data[Metadata <: Product, Payload <: Product] extends Product {
def metadata: Metadata
def payload: Payload
}
case class M()
case class P()
case class D(metadata: M, payload: P) extends Data[M, P]
我有Processor
处理Metadata
和Payload
的方式有所不同。
trait MetadataProcessor[Metadata <: Product] {
def apply() = "process metadata"
}
trait PayloadProcessor[Payload <: Product] {
def apply() = "process payload"
}
// both work
new MetadataProcessor[M]{}.apply() // "process metadata"
new PayloadProcessor[P]{}.apply() // "process payload"
我希望DataProcessor
能够同时处理Metadata
和Payload
。这是一种方法:
trait DataProcessor[Metadata <: Product, Payload <: Product] {
def apply() = {
new MetadataProcessor[Metadata]{}.apply() +
new PayloadProcessor[Payload]{}.apply()
}
}
new DataProcessor[M,P]{}.apply() // "process metadataprocess payload"
但是,我想调用new DataProcessor[D]{}.apply()
并获得完全相同的输出。怎么做?
对于具有以上代码的交互式Scala环境,请随时关注Scastie playground。
答案 0 :(得分:1)
尝试制作Metadata
和Payload
type members rather than type parameters,并使用类型投影Data#Metadata
,Data#Payload
。
trait Data extends Product {
type Metadata <: Product
type Payload <: Product
def metadata: Metadata
def payload: Payload
}
// This is optional, just in case if you need also type parameters Metadata and Payload.
// Then you can use them as Data.Aux[Metadata, Payload]
// object Data {
// type Aux[Metadata0 <: Product, Payload0 <: Product] = Data { type Metadata = Metadata0; type Payload = Payload0 }
// }
case class M()
case class P()
case class D(metadata: M, payload: P) extends Data { type Metadata = M; type Payload = P }
trait MetadataProcessor[Metadata <: Product] {
def apply() = "process metadata"
}
trait PayloadProcessor[Payload <: Product] {
def apply() = "process payload"
}
new MetadataProcessor[M]{}.apply() // "process metadata"
new PayloadProcessor[P]{}.apply() // "process payload"
trait DataProcessor[A <: Data] {
def apply() = {
new MetadataProcessor[A#Metadata]{}.apply() +
new PayloadProcessor[A#Payload]{}.apply()
}
}
new DataProcessor[D]{}.apply() // "process metadataprocess payload"