你也可以:
trait Foo {
type X
}
trait Bar extends Foo {
type X = String
}
class BarImpl extends Bar{
def getX:X="hi"
}
def baz[F <: Foo, T <: F#X](clz:F, x: T): Unit = { println("baz worked!")}
val bi = new BarImpl
val x: Bar#X = bi.getX
baz(bi,x)
但:
def baz2[F <: Foo, T <: F#X](x: T): Unit = { println("baz2 failed!")}
baz2(x)
失败:
test.scala:22: error: inferred type arguments [Nothing,java.lang.String] do not conform to method baz2's type parameter bounds [F <: this.Foo,T <: F#X]
baz2(x)
^
one error found
我认为基本上, F <: Foo 告诉编译器 F 必须是 Foo 的子类型,但是当它得到一个 X 时,它不知道你的特定X 来自哪个类。您的 X 只是一个字符串,不保留指向 Bar 的信息。
注意:
def baz3[F<: Foo](x : F#X) = {println("baz3 worked!")}
baz3[Bar]("hi")
也有效。你定义了一个 val x:Bar#X=??? 就是那个意思???仅限于 Bar#X 在编译时可能发生的任何事情......编译器知道 Bar#X 是字符串,因此 x 的类型只是一个字符串,与任何其他字符串没有区别。