When I’m writing this code, I’ve got a Compile error in Scala
var s: Stack[_ <: Number] = new Stack[Integer];
s.push(new Integer(1)); //compile-error: type mismatch; found :Integer required: _$bqjyh where type _$bqjyh <: Number
s.push(null); //compile-error: type mismatch; found : Null(null) required: _$2 where type _$2 <: Objects.Vehicle
This is equivalent to covariant collection in Java due the wildcard; it exact type in unknown, so we cannot added something to the stack.
But with lists I won’t get the same error:
var list: List[_ <: Number] = Nil;
var intList : List[Integer] = new Integer(1) :: Nil;
list = intList ; //no error
list = new Float(2) :: vehicles; //even float allowed
Now I can added even a float, but in fact I would believe the list is a List of Integers, so not Floats allowed.
1) Why is this allowed with lists, and not with Stacks? Is this due to the cons (::) operator?
2) What is the type of list? Is it dynamic?
3) Why is this allowed in Scala and not in Java?
4) Can I add something to the stack? (null is not working, in Java does because generic types only allows reference types)
::isn’t a mutating operation. This means thatx :: xswill return a List of typeList[ commonSupertypeOf[ typeOf[x], elementTypeOf[xs] ] ](this isn’t actual scala code, but I hope my point comes across), but it will not change the type ofxs. Ifxshas typeList[Float]andxhas typeInteger, then the expressionx :: xswill have typeList[Numeric], but the type ofxsis stillList[Float], so nothing breaks.addhowever is a mutating operation.xs.add(x)will add anIntegerto aStackwhose type isStack<Float>, which is clearly an error.This explains why doing
x :: xsis not dangerous. Now to explain why it typeckecks:The singnature of
::on aList[A]is:def :: [B >: A] (x: B) : List[B].What this means is that for any types
AandBwhereBis a supertype ofA,::given a value of typeBand a list of typeAwill produce a list of typeB. So when you do somesomeInteger :: someFloats, the compiler infers thatBisNumericandAisFloatand everything works.In java terms that would be
<B supertypeOf A> List<B> prepend(B item)except thatsupertypeOfisn’t legal java.