[英]Features of different kinds of path-dependent types in scala
假设有一个特征:
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
也相当于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)
T#InnerType
表示“属于某些 T的内部类型”,而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
签名读取:给定属于某些T的 x和InnerType,返回属于此x的InnerType。 但是在实现中,我们尝试返回y,它属于一个不一定与x相同的T,因此编译器会抱怨。
关于更新的小注释。
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)
编译
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.