【发布时间】:2017-08-02 23:41:03
【问题描述】:
trait Ingredient{}
case class Papperoni() extends Ingredient{}
case class Mushroom() extends Ingredient{}
trait ToppingDef[T] {
}
object PepperoniDef extends Serializable with ToppingDef[Papperoni] {
}
object MushroomDef extends Serializable with ToppingDef[Mushroom] {
}
class Oven[T <: Ingredient](val topping:ToppingDef[T]) {
}
class Pizza {
def cook = {
val topping =
if(someCondition()) { PepperoniDef }
else { MushroomDef}
new Oven(topping) // <-- build error here
}
}
我使用的是 Scala 2.11。这个例子有点做作,但我已经去掉了与问题无关的所有内容以提供一个简洁的例子。
我在最后一行得到的错误是:
Error:(26, 5) no type parameters for constructor Oven: (topping: ToppingDef[T])Oven[T] exist so that it can be applied to arguments (Serializable with ToppingDef[_ >: Papperoni with Mushroom <: Product with Serializable with Ingredient])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : Serializable with ToppingDef[_ >: Papperoni with Mushroom <: Product with Serializable with Ingredient]
required: ToppingDef[?T]
new Oven(topping)
但是,例如将最后一行更改为:
new Oven(PepperoniDef)
构建良好。所以当像这样显式传递参数时,编译器找到类型是没有问题的。
另外,从 PepperoniDef 和 MushroomDef 中删除 Serializable 特征,如下所示:
object PepperoniDef extends ToppingDef[Papperoni] {
}
object MushroomDef extends ToppingDef[Mushroom] {
}
也可以构建。但是在我的情况下,我需要 Serializable。
如果有必要,我想我可能可以重组代码来解决这个问题,但我想了解发生了什么,我不知道为什么在第一种情况下类型不明确,或者为什么存在 Serializable 特征有任何影响。提前感谢您提供任何见解。
编辑:感谢您的回复,非常有帮助。我认为最简洁的解决方法是改变这个:
val topping =
到这里:
val topping:ToppingDef[_ <: Ingredient] =
这可以解决构建错误并且不需要更改泛型类,我希望尽可能保持简单且未注释,以便让 Scala 推断出尽可能多的类型信息。
这并没有回答为什么Serializable 的存在对此有任何影响的问题。
【问题讨论】: