除非添加显式类型参数,否则为什么以下Scala代码无法编译?

时间:2009-06-24 12:54:54

标签: scala existential-type

object Test extends Application {

  // compiles:
  Map[Int, Value](
    0 -> KnownType(classOf[Object]),
    1 -> UnknownValue())

  // does not compile:
  Map(
    0 -> KnownType(classOf[Object]),
    1 -> UnknownValue())
}
sealed trait Value {
  def getType: Option[Class[_]]
}
case class UnknownValue() extends Value {
  def getType = None
  // compiles if changed to:
  // def getType: Option[Class[_]] = None
}
case class KnownType(typ: Class[_]) extends Value {
  def getType = Some(typ)
}

上面的代码无法编译。编译器的错误消息是:

Experiment.scala:10: error: type mismatch;
 found   : (Int, KnownType)
 required: (Int, Product with Value{def getType: Option[java.lang.Class[_$2]]}) where type _$2
    0 -> KnownType(classOf[Object]),
      ^
one error found

如果我将UnknownValue的方法声明更改为def getType: Option[Class[_]] = None,那么也会编译没有类型参数的Map()。

为什么?

3 个答案:

答案 0 :(得分:2)

嗯,这很奇怪。对我来说看起来像个错误。

您可以解决的一种方法是为Value提供一个默认值,然后只在KnownType中覆盖它。像这样:

sealed trait Value {
  def getType: Option[Class[_]] = None
}

case object UnknownValue extends Value

case class KnownType(typ: Class[_]) extends Value {
  override def getType = Some(typ)
}

但这看起来很可疑,就像你重新发明Option一样。我会完全跳过Value类型,只使用直接选项。

Map(
  0 -> Some(classOf[Object]),
  1 -> None)

如果您不希望每次预期其中一个地图时键入选项[类[_]],则可以为其创建别名:

type Value = Option[Class[_]]

答案 1 :(得分:1)

它确实看起来像一个错误,但是类型推断有很多问题,可以通过给它一些帮助来轻松解决。它编译如下:

Map(
  0 -> KnownType(classOf[Object]),
  1 -> (UnknownValue() : Value))

答案 2 :(得分:1)

我将问题发布到scala-user邮件列表,他们也说这是一个错误。