#scala
#scala
Вопрос:
Следующий код не будет компилироваться, и я не понимаю причин, почему нет
class FruitProcessor[T <: Fruit] {
def process(fruit: T) = {
// Do something with fruit
}
}
class FruitBlender[T <: Fruit] {
val fruitProcessor = new FruitProcessor[T]
def blend(fruit: T) = {
fruit match {
case b: Banana => fruitProcessor.process(b)
case a: Apple => fruitProcessor.process(a)
}
}
}
sealed trait Fruit
case class Banana(id: String) extends Fruit
case class Apple(id: String) extends Fruit
Ошибка компиляции примерно такая: «найден банан, требуется T»
Что я здесь делаю не так?
Комментарии:
1. Удалите
T
и замените егоFruit
.
Ответ №1:
process
Метод требует аргумент типа T
, но вы передаете ему значение типа Banana
. Компилятор недостаточно умен, чтобы понять, что T
это всегда Banana
находится в пути кода, где fruitProcessor.process(b)
вызывается. На самом деле вам вообще не нужно это выражение соответствия. В этом случае метод T
in blend
такой же, как и тот T
, который process
хочет. Так что вы можете просто позвонить fruitProcessor.process(fruit)
.
Ответ №2:
Чтобы объяснить, что вы делаете: У вас есть FruitProcessor
параметризованный подкласс T
Fruit
, который может process
T
s . Затем вы FoodBlender
также создаете параметризованный подкласс T
Fruit
, который имеет a FoodProcessor[T]
, то есть он может process
иметь все виды T
.
Поскольку вы можете использовать только process
T
and not [S <: Fruit]
, то есть только конкретные экземпляры вашего подтипа Fruit
T
, с которыми параметризован blender , а не все Fruit
s , это не может работать с конкретными типами Banana
and Apples
. T
FruitBlender
Например, на может быть class Pear extends Fruit
, и в этом случае подпись blend
будет def blend(fruit: Pear)
, что, конечно, если не совместимо с Apple
s или Banana
s.