代码如下。
我的期望是T
必须是B
或A
类型,因此调用lowerBound(new D)
可能不应该编译(?)。上限的类似实验给出了预期的类型检查错误。
感谢您提供提示。
object varianceCheck {
class A {
override def toString = this.getClass.getCanonicalName
}
class B extends A
class C extends B
class D extends C
def lowerBound[T >: B](param: T) = { param }
println(lowerBound(new D)) //> varianceCheck.D
}
答案 0 :(得分:4)
通过实施,您可以写下:
scala> def lowerBound[T >: B](param: T) = { param }
lowerBound: [T >: B](param: T)T
scala> lowerBound(new AnyRef {})
res0: AnyRef = $anon$1@2eef224
其中AnyRef
是所有对象/引用类型的超类型(实际上它是Java Object
类的别名)。这是正确的,T >: B
表示类型参数T
或抽象类型T
引用类型B
的超类型。
你只有toString
的错误示例,因为此方法包含所有对象类型,但是如果将其更改为,请说someMethod
,lowerBound
将无法编译:
<console>:18: error: value someMethod is not a member of type parameter T
def lowerBound[T >: B](param: T) = { param.someMethod }
如果您将其更改为T <: B
,这意味着T
类型的参数是B
的子类,那么一切都很好,因此param
已someMethod
1}}方法:
def lowerBound[T <: B](param: T) = { param.someMethod }
答案 1 :(得分:3)
也遇到同样的问题。似乎编译器做得很出色,可以帮助我们立足。如果提取lowerBound的结果,您可能会注意到它的类型为B
val b: B = lowerBound(new D)
println(b) //> varianceCheck.D
然后,如果您尝试显式请求D类型
lowerBound[D](new D)
您将看到预期的编译器错误:
错误:(12,21)类型参数[D]不符合方法lowerBound的类型参数界限[T>:B] lowerBound [D](新D)