Scala:双重F-Bounded多态类型的伴随对象

时间:2015-04-15 13:38:21

标签: scala polymorphism parametric-polymorphism

我有一个F-Bound类型:

sealed trait A[AA <: A[AA]] {
  self: AA =>
}

第二种F-Bound类型,由第一种类型参数化。

sealed trait B[BB <: B[BB, AA], AA <: A[AA]] {
  self: BB =>
  val content: AA
}

我很乐意编写使用这些类型的案例类:

case class BInst[BB <: BInst[BB, AA], AA <: A[AA]](content: AA) 
     extends B[BInst[BB, AA], AA]

现在我想为case类创建一个伴随对象,我可以通过特征B引用它,例如:

sealed trait A[AA <: A[AA]] { self: AA => }

sealed trait B[BB <: B[BB, AA], AA <: A[AA]] {
  self: BB =>
  val content: AA
  def companion: Companion[BB]
}

case class BInst[BB <: BInst[BB, AA], AA <: A[AA]](content: AA) 
     extends B[BInst[BB, AA], AA] {
  def companion: Companion[BInst[BB, AA]] = BInst
}

sealed trait Companion[+BB <: B[_, _]]
object BInst extends Companion[BInst]

但是这无法编译,因为伴随参数化(最后一行)中的BInst需要类型参数。 类似地

sealed trait Companion[BB[X, Y] <: B[X, Y]]

失败。伴侣对象的正确类型是什么?

1 个答案:

答案 0 :(得分:1)

我看到的唯一方法是放弃Companion / BInst的通用参数,因为即使从类型透视图中只有一个对象实例(只有一个BInst.type类型):< / p>

scala> sealed trait A[AA <: A[AA]] { self: AA => }

sealed trait B[BB <: B[BB, AA], AA <: A[AA]] {
  self: BB =>
  val content: AA
  def companion: Companion[_]
}

case class BInst[BB <: BInst[BB, AA], AA <: A[AA]](content: AA)
     extends B[BInst[BB, AA], AA] {
  def companion = BInst
}

sealed trait Companion[+BB <: B[_, _]]
object BInst extends Companion[BInst[_, _]]

defined trait A
defined trait B
defined class BInst
defined trait Companion
defined module BInst

之后你可能会实际投出你的BInst(内部案例类):

def companion: Companion[BInst[BB, AA]] = 
    BInst.asInstanceOf[Companion[BInst[BB, AA]]

如果您不在Companion - 特质/ BInst - 对象中投放类型(最好只使用BB / AA -independent方法BInst class)没有获得ClassCastException的风险,.asInstanceOf[Companion[BInst[BB, AA]]]将为您创建(克隆)新类型,使用BInst作为原型。