我遇到了我无法理解的类型检查错误。两段代码是相似的,但只有一段编译。编译器提供完全无用的错误消息:
错误:类型参数[I]不符合类型DY的类型参数边界[I&lt ;: Sample.this.Y]
有问题的代码:
trait Sample {
type X
type DX[I <: X] <: X
type Y = Aux[X]
type DY[I <: Y] <: Y
type Z = Bux[X]
type DZ[I <: Z] <: Z
type DW[I <: Z#C] <: Z#C
}
type Aux[I] = Sample { type X = I }
trait Dep {
type B
type C = Aux[B]
}
type Bux[A] = Dep { type B = A }
type UseX[I <: S#X, S <: Sample] = S#DX[I] // ok
type UseY[I <: S#Y, S <: Sample] = S#DY[I] // fails
type UseZ[I <: S#Z, S <: Sample] = S#DZ[I] // ok
type UseW[I <: S#Z#C, S <: Sample] = S#DW[I] // fails
为什么我无法引用类型本身?
我和写这个问题的时候一样困惑。但我仍然设法欺骗编译器完成他的工作。这只会加剧我的困惑。
问题是基于类型绑定接受或拒绝相同类型的参数。如果类型绑定与参数相同(因此引入递归),则拒绝它。但是如果我在一个类型中包装递归,它通常会被接受。所以我需要的是中继递归调用
trait Sample {
type X
type Y = Aux[X]
type Z = Bux[X]
type DY[I <: Y] <: Y
type DD[I <: Z] = DY[I#C]
}
type UseY[I <: S#Y, S <: Sample] = S#DY[I] // still fails
type UseD[I <: S#Z, S <: Sample] = S#DD[I] // miraculously works
但它需要在Bux
包装器类型中包装每个类型级别的调用。
答案 0 :(得分:1)
因此,S#Y
表示“某些类型Y
,在 S
的任何实例中定义。
另一方面,type DY[I <: Y]
表示“I
必须是此实例中声明的Y
的子类”。
因此,当您说type UseY[I <: S#Y, S <: Sample] = S#DY[I]
时,它会失败,因为I
被限制为来自某些 Y
的{{1}}的子类,但是S
希望它是的子类 DY
,其中声明了S
。