on code below.
My expectation is that T
must be a of type B
or A
, so call to lowerBound(new D)
should probably not compile (?). Similar experiments with upperbound give me expected typecheck errors.
Thanks for giving the hint.
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
}
With your implementation you can write:
scala> def lowerBound[T >: B](param: T) = { param }
lowerBound: [T >: B](param: T)T
scala> lowerBound(new AnyRef {})
res0: AnyRef = $anon$1@2eef224
where AnyRef
is a super type of all object/reference types (actually it is an alias for Java Object
class). And this is right, T >: B
expresses that the type parameter T
or the abstract type T
refer to a supertype of type B
.
You just have a bad example with toString
, cause this method has all object types, but if you change it to, let's say on someMethod
, your lowerBound
won't compile:
<console>:18: error: value someMethod is not a member of type parameter T
def lowerBound[T >: B](param: T) = { param.someMethod }
If you change this to T <: B
, which means that parameter of type T
is a subclass of B
, than everything is good, cause this param
has someMethod
method:
def lowerBound[T <: B](param: T) = { param.someMethod }