Почему следующий код Scala не компилируется, если не добавлены явные параметры типа?

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 () без параметров типа.

Почему?


person Esko Luontola    schedule 24.06.2009    source источник


Ответы (3)


Хм, это странно. Мне кажется, это ошибка.

Один из способов исправить это - присвоить Value значение по умолчанию для getType, а затем только переопределить его в 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. Я бы вообще пропустил тип значения и просто использовал бы прямые параметры.

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

Если вам не нравится набирать Option [Class [_]] каждый раз, когда вы ожидаете одну из этих карт, вы можете создать для нее псевдоним:

type Value = Option[Class[_]]
person Jorge Ortiz    schedule 24.06.2009
comment
Это минимальный пример воспроизведения проблемы. В реальном коде есть и другие классы case, так что это не просто новое изобретение Option. - person Esko Luontola; 25.06.2009

Это действительно похоже на ошибку, но есть много проблем с выводом типа, которые можно легко обойти, оказав ему небольшую помощь. Он компилируется так:

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

Я отправил вопрос в список рассылки scala-user, и они сказали, что это ошибка.

person Esko Luontola    schedule 25.06.2009