An example ListNode taken from the Scalas homepage looks like this:
case class ListNode[+T](h: T, t: ListNode[T]) { def head: T = h def tail: ListNode[T] = t def prepend[U >: T](elem: U): ListNode[U] = ListNode(elem, this) }
Using this class, we can create objects such as:
val empty: ListNode[Null] = ListNode(null, null) val strList: ListNode[String] = empty.prepend("hello") .prepend("world") val anyList: ListNode[Any] = strList.prepend(12345)
As we can see, we can add an integer value to the String node. I think this works because a parameter of type U will be automatically set to Any if an integer with prepend method is given (because Int not a supertype of String ).
When I try this using my own example with a lower bound, I get an error:
scala> class E[T >: String] defined class E scala> new E[Any] res1: E[Any] = E@135f0a scala> new E[Int] <console>:11: error: type arguments [Int] do not conform to class E type param eter bounds [T >: String] val res2 = ^ <console>:12: error: type arguments [Int] do not conform to class E type param eter bounds [T >: String] new E[Int] ^
Why is the Int type not automatically considered here as the Any type, as in the ListNode example?
UPDATE 1 . This also works (without explicitly indicating that the new ListNode should be of type Any )
scala> val empty: ListNode[Null] = ListNode(null, null) empty: example.listNode.ListNode[Null] = ListNode(null,null) scala> empty.prepend("hello").prepend("world") res0: example.listNode.ListNode[java.lang.String] = ListNode(world,ListNode(hell o,ListNode(null,null))) scala> val strList: ListNode[String] = empty.prepend("hello").prepend("world") strList: example.listNode.ListNode[String] = ListNode(world,ListNode(hello,ListN ode(null,null))) scala> strList.prepend(12345) res1: example.listNode.ListNode[Any] = ListNode(12345,ListNode(world,ListNode(he llo,ListNode(null,null))))