= Solution
Use a covariant element type and a lower type bound when adding potentially more general elements:
``
class VendingMachine[+A](val currentItem: Option[A], items: List[A]) {
def this(items: List[A]) = this(None,items)
def dispenseNext(): VendingMachine[A] = items match {
case Nil =>
if (currentItem.isDefined) new VendingMachine[A](None,Nil)
else this
case t :: ts => new VendingMachine[A](Some(t),ts)
}
def addAll[B >: A](newItems: List[B]): VendingMachine[B] =
new VendingMachine[B](items ++ newItems)
}
``
The <lower type bound> permits the old pending elements of type `A` to be used as type `B`, so concatenation is type-correct. The resulting machine is immutable and can return the wider type without changing the existing machine. With the given client expressions, `VM1` has type `VendingMachine[Juice]` and `VM2` can have type `VendingMachine[Drink]`. The supplied `addAll` body constructs a new pending-item machine; its constructor sets `currentItem` to `None`.
Back to article page