2015-04-16 29 views
2

我有三F-绑定类型AB & C,其中BA参数化的,并且CB参数化(并因此也通过A)。我可以实例化AB,但是当我尝试实例化C时,编译器无法推断出这些类型。如果我明确地给出它的类型,一切都可行 - 但这些类型丢失似乎相当愚蠢(这是由于类型擦除?)。构建三级深F-绑定类型

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

case class AInst(data: String) extends A[AInst] 

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

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

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

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

val a1 = new AInst("A1") 
val b1 = BInst(a1) 
val c1 = CInst[BInst[AInst],AInst](b1) 

有一个变通,在那里我没有为CInst专门指定的类型?

我目前使用类型参数化来实现F-Bounds,但是会切换到抽象类型成员来解决这个问题吗?上课怎么样?

+0

我在这里的例子:https://stackoverflow.com/questions/1154571/scala-abstract-types-vs-generics/10891994#10891994 – ayvango

回答

1

怎么样:

... //A,AInst,B,BInst without changes 

sealed trait C[CC <: C[CC, BB, AA], BB <: B[BB, AA], AA <: A[AA]] { 
    self: CC => 
    val content: B[BB, AA] //`B[BB, AA]` instead of `BB` 
} 

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

用法:

scala> val a1 = new AInst("A1") 
a1: AInst = AInst(A1) 

scala> val b1 = BInst(a1) 
b1: BInst[AInst] = BInst(AInst(A1)) 

scala> val c1 = CInst(b1) 
c1: CInst[BInst[AInst],AInst] = CInst(BInst(AInst(A1))) 

这并不像看到的BBBInst[AA <: A[AA]]编译器之前的工作,所以我B[BB,AA]刚刚解禁BBB[BInst[AInst], AInst]

P.S.对于类型成员,您仍然推动以某种方式将类型传递给您的案例类,所以没有太大区别。

+0

太好了,谢谢!我非常接近...类型定义变得稍微笨拙,我不知道这是否也是代码异味的一种形式。 – Karalga

+0

这取决于你如何看待它们:)我将它们视为编译时'def's [像这里](http://stackoverflow.com/a/29470018/1809978)。但是编译器类型推理可能不那么清楚,实际上它非常依赖于你的领域逻辑,你可能真的不需要它们 – dk14