This code seems to set up a contravariant example: FruitBox can take in Apples or Oranges.
class Fruit(name: String) { }
case class Apple(name: String) extends Fruit(name) {}
case class Orange(name: String) extends Fruit(name) {}
class Box[-T] {
type U >: T
def put(t: U): Unit= {box += t}
val box = scala.collection.mutable.ListBuffer[U]()
}
object test {
val FruitBox = new Box[Fruit]
// Fruit Box takes in everything
FruitBox.put(new Fruit("f1"))
FruitBox.put(new Orange("o1"))
FruitBox.put(new Apple("a1"))
// and Orange Box takes in only oranges
val OrangeBox = new Box[Orange]
//OrangeBox.put(new Apple("o2") ==> Compile Error that makes sense
OrangeBox.put(new Orange("o2"))
// Contra-variant nature is also demonstrated by
val o: Box[Orange] = FruitBox
}
That is all fine...but why does it work ? specifically: 1. When the FruitBox is initialized, why does the "type U >: T" not constrain it to supertypes of Fruit? In spite of that constraint, the FruitBox is able to put the subtypes if Fruit ( oranges and apples )...how?
First, while Scala allows you to write new Box[Fruit], leaving U an abstract member, I don't understand why. However, Scala seems to assume The only thing Scala knows about U = T in this case. Since your code never implements U, it can just be replaced by T. So you end up with def put(t: Fruit) in FruitBox: of course it accepts Apples, since they are Fruits!U is that it's a supertype of T; thus T is a subtype of U, and so is every subtype of T. So any subtype of Fruit can be passed to FruitBox.put. So def put(t: U): Unit is effectively the same as put(t: T): Unit unless you implement U as in new Box[Fruit] { type U = Object }.
a FruitBox that can put apples and oranges, and an OrangeBox that can only put oranges. That looks like contra-variant behavior, and I am fine with it.
It isn't at all contravariant behavior; you'll get exactly the same with
class Box[T] {
def put(t: T): Unit= {box += t}
val box = scala.collection.mutable.ListBuffer[T]()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With