简体   繁体   中英

Scala Generic: The return data type of a method with lower bound type

I've defined some Scala classes:

class Drink
class SoftDrink extends Drink
class Cola extends SoftDrink

class VendingMachine[A](val currentItem: Option[A], items: List[A]) {
  def this(items: List[A]) = this(None, items)

  def addAll[B >: A](newItems: List[B]): VendingMachine[B] =
    new VendingMachine(items ++ newItems)
}

Then I ran the following code snippet:

val colasVM: VendingMachine[Cola] = new VendingMachine(List(new Cola, new Cola))
// It works
val softDrinksVM: VendingMachine[Drink] = colasVM.addAll(List(new SoftDrink))
// Compile Error: You may wish to define A as +A instead. (SLS 4.5)
val softDrinksVM2: VendingMachine[Drink] = new VendingMachine[SoftDrink](None, null) 

In my opinion, colasVM.addAll(List(new SoftDrink)) returns VendingMachine[SoftDrink] type data, and it can't be assigned to a VendingMachine[Drink] variable since they're not the same type.

However val softDrinksVM: VendingMachine[Drink] = colasVM.addAll(List(new SoftDrink)) can be compiled successfully in my side, can anyone help explain why?

Thanks so much!

That happens because of the lower bound type, type inference and covariance.

colasVM is a VendingMachine[Cola], so its type parameter A is Cola.

Method addAll has a type parameter B that is any super type of A. If A is Cola, B can be Cola, SoftDrink, Drink, it can even be AnyRef or Any.

When you call addAll you are not telling to the compiler which type is B, so it has to infer it. If softDrinksVM2 is of type VendingMachine[Drink], B has to be Drink.

Why your code compiles? Because List is covariant, so a List[SoftDrink] is a List[Drink].

As you can see is even possible to do something like this.

val softDrinksVM1: VendingMachine[AnyRef] = colasVM.addAll(List(new Object))
val softDrinksVM2: VendingMachine[AnyRef] = colasVM.addAll(List(new SoftDrink))

Take a look to this link for more information https://docs.scala-lang.org/tour/variances.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM