Assume the following declarations made into the Scala repl:
class Animal
class Bird extends Animal
class Chicken extends Bird
type SubType = t forSome { type t <: Bird }
type SuperType = t forSome { type t >: Bird }
As I expect, SubType
is of a type that conforms to Bird
. Since Animal
is a superclass of Bird
, a variable of type SubType
cannot hold value of type Animal
:
scala> val foo: SubType = new Animal
<console>:10: error: type mismatch;
found : Animal
required: SubType
val foo: SubType = new Animal
and yet this corollary is not as I expect:
scala> val foo: SuperType = new Chicken
foo: SuperType = Chicken@1fea8dbd
The assignment succeeds, and so do these:
scala> val foo: SuperType = 2
foo: SuperType = 2
scala> val foo: SuperType = "wtf?"
foo: SuperType = wtf?
scala>
Again, here's SuperType
:
type SuperType = t forSome { type t >: Bird }
According to SLS 4.3,
A type declaration type t [tps ] >: L <: U declares t to be an abstract type with lower bound type L and upper bound type U.
So I'm declaring t
to be an abstract type with lower bound Bird
. Chicken
is not a superclass of Bird
, neither are String
nor Int
.
I thought that maybe it's because a Chicken
is an Any
and a SuperType
can store an Any
. But if I change the declaration of SuperType
to this:
type SuperType = t forSome { type t >: Bird <: Animal}
to set an upper bound of Animal
nothing seems to change.
Questions
First
How are my assignments of values of types Chicken
Int
and String
to a SuperType
variable allowed by existential clauses { type t >: Bird }
and { type t >: Bird <: Animal}
?
Second
What is the significance of the word "abstract" in the quoted specification that "A type declaration type t [tps ] >: L <: U declares t to be an abstract type..." What would the difference in meaning be if the word "abstract' were not there?