次のクラス定義を検討してください。
class Person[+T <: Person[T]]
class Student() extends Person[Student]
class Professor() extends Person[Professor]
学生と教授のリストが欲しいです。
val persons = List(new Student(), new Professor())
しかし、これは次のエラーでコンパイルに失敗します:
type arguments [Person[Person[Any]]] do not conform to class Person's type parameter bounds [+T <: Person[T]]
関連する以前の質問How to define case classes with members with unbound type parameters?に対する Daniel C. Sobral の回答に感謝します。ここでは、実存型がそのトリックを行うことを知っています。これはコンパイルされます:
val persons = List[Person[T] forSome {type T <: Person[T]}](new Student(), new Professor())
<: Person[T]
この問題は、クラス Person の宣言の型パラメーターの上限によって引き起こされます。上限を削除すると、コンパイラーはリストの型パラメーターを推測してコンパイルList[Person[Person[Person[Any]]]]
できるようになります。
質問
- コンパイラは、リストをコンパイルするタイプを推論できないのはなぜですか?
- 存在型は冗長性が最も低く、さらにトリッキーになる可能性があります (上記の私の以前の質問に対するダニエルの回答を参照してください): 学生と教授のリストを作成するための明示的な存在型に代わるものはありますか?