Я изучаю понятие дисперсии типов и границ в scala и как их использовать. Я сталкивался с вопросом о переполнении стека ниже, где одно из решений упоминало, как предотвратить обобщение типов в scala.
Параметр ковариантного типа
Ниже приведен код, размещенный в решении. В приведенном ниже коде как помогает добавление нового параметра типа C? Я понимаю, как ограничен B (как супертип A и подтип Fruit). Но я совершенно заблудился относительно того, что здесь делает С. Почему это должен быть супер тип A. Почему неявное доказательство требует, чтобы B был подтипом C?
И почему при добавлении объекта List of Orange возникает несущественная ошибка, что Fruit не является подтипом Banana. Может кто-нибудь объяснить это?
Я предполагаю, что для удовлетворения первого ограничения объект Orange обозначается как объект Fruit, но после этого теряется из-за того, что он говорит, что Fruit не является подтипом Banana.
case class Banana() extends Fruit
defined class Banana
case class Orange() extends Fruit
defined class Orange
case class Basket[+A <: Fruit](items: List[A]) {
// ...
def addAll[B >: A <: Fruit, C >: A](newItems: List[B])(implicit ev: B <:< C): Basket[B] =
new Basket(items ++ newItems)
// ...
}
defined class Basket
val bananaBasket: Basket[Banana] = Basket(List(Banana(), Banana()))
bananaBasket: Basket[Banana] = Basket(List(Banana(), Banana()))
bananaBasket.addAll(List(Orange())) // not accepted
Main.scala:593: Cannot prove that Product with Serializable with cmd27.Fruit <:< cmd47.Banana.
bananaBasket.addAll(List(Orange()))