Pourquoi le code Scala suivant ne compile-t-il que si des paramètres de type explicite sont ajoutés?
-
10-07-2019 - |
Question
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)
}
La compilation du code ci-dessus a échoué. Le message d'erreur du compilateur est le suivant:
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
Si je change la déclaration de méthode de UnknownValue
en def getType: Option [Class [_]] = None
, la compilation Map () sans paramètre de type est également compilée.
Pourquoi?
La solution 3
J'ai posté la question sur la liste de diffusion de scala-user et ils ont également dit qu'il s'agissait d'un bug.
Autres conseils
Hmm, c'est bizarre. Ça ressemble à un bug pour moi.
Vous pouvez résoudre ce problème en donnant à Value une valeur par défaut pour getType, puis en le remplaçant uniquement dans KnownType. Comme si:
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)
}
Mais cela ressemble étrangement à une réinvention d'Option. Je saute complètement le type de valeur et n'utilise que des options droites.
Map(
0 -> Some(classOf[Object]),
1 -> None)
Si vous n'aimez pas taper Option [Class [_]] chaque fois que vous attendez l'une de ces cartes, vous pouvez créer un alias pour cette dernière:
type Value = Option[Class[_]]
Cela ressemble à un bogue, mais il existe de nombreux problèmes avec l’inférence de type qui peuvent facilement être contournés en lui donnant un peu d’aide. Il compile comme ceci:
Map(
0 -> KnownType(classOf[Object]),
1 -> (UnknownValue() : Value))