6

假设有一个特征:

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)someAlgosomeAlgoObjObj是最正确的功能;2)在这个例子中使用泛型函数根本没有意义。

我想澄清一下上述通用函数之间的一些区别。请纠正我,如果我犯了错误。

因此,据我了解,类型T对应于(调用它)的静态类型或泛型调用的显式类型(我的意思是例如)。这就是为什么在 type 的声明中对应于 type 。但也对应于静态类型的。区别在哪里?xXalgo[Int]T#InnerTypeXx.InnerTypeInnerTypex

进一步...编译,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:我发现它们之间存在一个区别someAlgoObjObjsomeAlgoTypeType如果将它们与显式类型参数一起使用。如果我们编写一些扩展类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)
4

2 回答 2

0

关于更新的小说明。

someAlgoTypeType[OuterTrait](x)(y) 

失败是因为您的方法签名告诉它希望其y参数符合类型T#InnerType并且您y.type是 Int。要使其工作,您应该将其类型更改为以下内容:

class OuterIntClass extends OuterTrait{
  type InnerType = Int
}
val x: OuterIntClass = new OuterIntClass()
val y: x.InnerType = 5

nowy的类型满足类型投影T#InnerTypesomeAlgoTypeType[OuterTrait](x)(y)编译

于 2013-06-24T06:33:55.730 回答
0

T#InnerType表示“属于某个T 的 InnerType”,而x.InnerType表示“属于给定x(属于 OuterTrait 类型)的 InnerType”。

理解这些的关键在于某些 T给定的 x。您可以将一些解释一些T,但我们不解释哪个 T 实例,这意味着两个 T 中不一定相同,因此,不能证明 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 = ???
  1. 给定 x 和属于此 x的 InnerType 返回其 InnerType。
  2. 给定 x 和属于此 x的InnerType 返回属于某个 T的 InnerType ,这意味着某个 T不一定与 x 相同。
  3. 给定 x 和属于某个 T的 InnerType 返回属于某个T 的 InnerType

现在是第四个:

def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = y

签名内容为:给定 x 和属于某个 T的 InnerType,返回属于此 x的 InnerType 。但是在实现中,我们尝试返回 y,它属于不一定与 x 相同的 T,因此编译器会抱怨。

于 2013-06-23T17:15:01.873 回答