假设有一个特征:
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
对应于{em>静态类型的x
(称之为X
)或显式类型的通用调用(我的意思是{{例如1}}。这就是为什么algo[Int]
对应于T#InnerType
类型声明中的类型的原因。但X
也对应x.InnerType
的静态类型的InnerType
。区别在哪里?
此外...... x
会进行编译,因此someAlgoObjType
似乎必须是x.InnerType
的子类型。那么T#InnerType
无法编译就可以了,因为我们不能隐式地进行向下转换。虽然我们可以重写最后一个:
someAlgoTypeObj
UPD1:如果将def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = {
pairPrintln(x, y)
y.asInstanceOf[x.InnerType]
}
和someAlgoObjObj
与明确的类型参数一起使用,我发现它们之间存在差异。如果我们写一些扩展someAlgoTypeType
的类:
OuterTrait
然后:
class OuterIntClass extends OuterTrait{
type InnerType = Int
}
val x: OuterIntClass = new OuterIntClass()
val y: Int = 5
并且下次通话无效:
someAlgoObjObj[OuterTrait](x)(y) // OK
答案 0 :(得分:0)
T#InnerType
表示“某些 T中属于的InnerType”,而x.InnerType
表示“给定 x中的属性的内部类型”(类型为OuterTrait) )”。
理解这些的关键在于给定x 中的某些T vs 中的。您可以将某些中的解释为某些T但我们没有哪个T实例,这意味着在两个Ts中不一定相同,所以,T#InnerType可以不能被证明等于另一个T#InnerType。
让我们分析一下签名:
/* 1 */ def someAlgoObjObj[T <: OuterTrait](x: T)(y: x.InnerType): x.InnerType = ???
/* 2 */ def someAlgoObjType[T <: OuterTrait](x: T)(y: x.InnerType): T#InnerType = ???
/* 3 */ def someAlgoTypeType[T <: OuterTrait](x: T)(y: T#InnerType): T#InnerType = ???
现在是第四个:
def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = y
签名读取:给定x和属于某些T 的InnerType,返回属于 this x 的InnerType。但是在实现中,我们尝试返回y,它属于一个不一定与x相同的T,因此编译器会抱怨。
答案 1 :(得分:0)
关于更新的小记录。
someAlgoTypeType[OuterTrait](x)(y)
Failes,因为您的方法签名告诉它期望其y
参数符合类型T#InnerType
而您的y.type
是Int。要使其工作,您应该将其类型更改为以下内容:
class OuterIntClass extends OuterTrait{
type InnerType = Int
}
val x: OuterIntClass = new OuterIntClass()
val y: x.InnerType = 5
现在y
的类型符合类型投影T#InnerType
和someAlgoTypeType[OuterTrait](x)(y)
编译