假设有一个特征:
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
对应于(调用它)的静态类型或泛型调用的显式类型(我的意思是例如)。这就是为什么在 type 的声明中对应于 type 。但也对应于静态类型的。区别在哪里?x
X
algo[Int]
T#InnerType
X
x.InnerType
InnerType
x
进一步...编译,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)