以下を考慮してください (Scala 2.8.1 および 2.9.0 でテスト済み):
trait Animal
class Dog extends Animal
case class AnimalsList[A <: Animal](list:List[A] = List())
case class AnimalsMap[A <: Animal](map:Map[String,A] = Map())
val dogList = AnimalsList[Dog]() // Compiles
val dogMap = AnimalsMap[Dog]() // Does not compile
最後の行は次のように失敗します。
error: type mismatch;
found : scala.collection.immutable.Map[Nothing,Nothing]
required: Map[String,Main.Dog]
Note: Nothing <: String, but trait Map is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: String`. (SLS 3.2.10)
Error occurred in an application involving default arguments.
val dogMap = AnimalsMap[Dog]() // Does not compile
^
one error found
これを変更するとval dogMap = AnimalsMap[Dog](Map())
修正されますが、デフォルトの引数値を利用できなくなります。
リストの対応物が期待どおりに機能するのに、デフォルト値が Map[Nothing,Nothing] と推論されるのはなぜですか? 引数のデフォルト値を使用する AnimalsMap インスタンスを作成する方法はありますmap
か?
編集:私は、より差し迫った 2 番目の質問への回答を受け入れましたが、キーの型Map()
がこれら 2 つのケースで異なって推論される理由を知りたいと思います。
case class AnimalsMap1(map:Map[String,Animal] = Map())
val dogs1 = AnimalsMap1() // Compiles
case class AnimalsMap2[A <: Animal](map:Map[String,A] = Map())
val dogs2 = AnimalsMap2[Dog]() // Does not compile
編集2:型の境界は無関係であるようです-ケースクラスへのパラメトリック型は問題を引き起こします:
case class Map3[A](map:Map[String,A] = Map())
val dogs3 = Map3[Dog]() // Does not compile