【发布时间】:2010-10-02 06:47:45
【问题描述】:
我想将一些来自不同类型层次结构的对象存储到List[Any] 或类似容器中,但稍后对它们执行隐式转换以执行类型类之类的操作。
这是一个例子:
abstract class Price[A] {
def price(a: A): Int
}
trait Car
case class Prius(year: Int) extends Car
trait Food
case class FriedChicken() extends Food
object Def {
// implicit object AnyPrices extends Price[Any] {
// def price(any: Any) = 0
// }
// implicit object PriusPrices extends Price[Prius] {
// def price(car: Prius) = 100
// }
implicit object CarPrices extends Price[Car] {
def price(car: Car) = 100
}
implicit object FoodPrices extends Price[Food] {
def price(food: Food) = 5
}
}
def implicitPrice[A: Price](x: A) = implicitly[Price[A]].price(x)
import Def._
val stuff: List[Any] = List(Prius(2010), FriedChicken())
stuff map { implicitPrice(_) }
以上代码抛出错误如下:
error: could not find implicit value for evidence parameter of type Price[Any]
stuff map { implicitPrice(_) }
^
如果您取消注释 AnyPrices,您会得到 List(0,0),但这不是我所期望的。
我是否必须将清单存储到列表中才能正常工作?
另外,List(Prius(2010)) map { implicitPrice(_) } 也不起作用,因为它想要 Price[Prius] 和 Price[Car] 还不够好。有没有办法让它更灵活?
【问题讨论】:
-
隐式是静态选择的。鉴于您的列表包含不相关的类型,它的静态类型是
List[Any],这说明了您所看到的行为。 -
您能提出任何解决方法吗?
Manifest[_]#erasure.cast也返回Any。 -
两件事:1)我对您列表的推断类型有误。它实际上是
List[Price],但您将stuff明确键入为List[Any]; 2) 底线是,implicits 是一个静态解析的构造,而您想要对任何给定产品的价格确定方法进行动态解析。我建议也许采用特征/混合方法。 -
即使隐式转换可用,推断的类型似乎是
List[Product]。res0: List[Product] = List(Prius(2010), FriedChicken())。因为我可以存储比Product更低的类型,比如String,所以我强制使用Any,但这似乎并不重要,因为隐式只适用于类型而不适用于超类型。