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 }