【发布时间】:2013-06-20 04:21:01
【问题描述】:
假设有一个特质:
trait OuterTrait {
type InnerType
}
现在我们可以编写非泛型函数someAlgo:
def pairToString[S, U](x: S, y: U): String =
"{" + y.toString + " in " + x.toString + "}"
def pairPrintln[S, U](x: S, y: U) {
println(pairToString(x, y))
}
def someAlgo(x: OuterTrait)(y: x.InnerType): x.InnerType = {
pairPrintln(x, y)
y
}
以及一系列通用函数:
def someAlgoObjObj[T <: OuterTrait](x: T)(y: x.InnerType): x.InnerType = {
pairPrintln(x, y)
y
}
def someAlgoObjType[T <: OuterTrait](x: T)(y: x.InnerType): T#InnerType = {
pairPrintln(x, y)
y
}
def someAlgoTypeType[T <: OuterTrait](x: T)(y: T#InnerType): T#InnerType = {
pairPrintln(x, y)
y
}
还有一个通用函数无法编译:
def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = {
pairPrintln(x, y)
y
}
似乎:
1)someAlgo和someAlgoObjObj是最正确的函数;
2)在这个例子中使用泛型函数根本没有意义。
我想澄清一下上述通用函数之间的一些区别。如果我犯了错误,请纠正我。
据我了解,T 类型对应于x 的静态 类型(称为X)或泛型调用的显式类型(例如,我的意思是algo[Int])。这就是为什么T#InnerType 对应于X 类型声明中的类型。但是x.InnerType也对应x的static类型的InnerType。区别在哪里?
Further... someAlgoObjType 编译,所以看来x.InnerType 必须是T#InnerType 的子类型。那么someAlgoTypeObj 不编译就可以了,因为我们不能隐式地进行向下转换。虽然我们可以重写最后一个:
def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = {
pairPrintln(x, y)
y.asInstanceOf[x.InnerType]
}
UPD1:如果将它们与显式类型参数一起使用,我发现someAlgoObjObj 和someAlgoTypeType 之间存在一个区别。如果我们写一些扩展OuterTrait的类:
class OuterIntClass extends OuterTrait{
type InnerType = Int
}
val x: OuterIntClass = new OuterIntClass()
val y: Int = 5
然后:
someAlgoObjObj[OuterTrait](x)(y) // OK
下一个电话不起作用:
someAlgoTypeType[OuterTrait](x)(y)
【问题讨论】:
-
PDT 上有一个很棒的blogpost,你一定要看看它
-
谢谢,这很有趣。但我对
T#InnerType仍有问题...