1

次のクラス定義を考えてみましょう:型推論入力paramenters

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]] 

Daniel C. Sのおかげで私の関連する以前の質問へのobralの答えHow to define case classes with members with unbound type parameters?私は実在のタイプがここでトリックをするだろうと知っています。これは、コンパイルされます。

val persons = List[Person[T] forSome {type T <: Person[T]}](new Student(), new Professor()) 

問題は、クラスPersonの宣言の型パラメータに上限<: Person[T]によって引き起こされます。上限を削除すると、コンパイラはコンパイルするリストの型パラメータを推測できるようになります。List[Person[Person[Person[Any]]]]までは私が見ることができます。

質問

  1. なぜコンパイラがコンパイルになるだろう、リストのための任意の型を推論することはできませんか?
  2. 存在タイプは最も冗長であり、さらに難しいかもしれません(上記の前の質問に対するDanielの回答を参照してください):生徒と教授のリストを作成するための明示的な存在タイプの代わりがありますか?
+0

あなたは 'Person'ため、このような複雑でジェネリック型を必要としないのはなぜ?あなたの例でコンパイラが推測するものは何でしょうか? – paradigmatic

+0

@ paradigmaticこれは、タイプPersonが拡張型であることを知るためのものです。このように 'Person'の' def동료:Seq [T] 'メソッドを定義して、' Student'のインスタンスを返すメソッドと 'Professor'のインスタンスのための教授を返すことができます。そして、私が作成したListオブジェクトの型引数を推論するために、コンパイラに伝えたいと思います。 –

+0

@paradigmatic申し訳ありませんが、私は初めてそれを逃しました:私は本当にどのようなタイプ、エラーを生成しないだけ気にしません。これは、実在の型でも、 'Person [_]'でもかまいません。意味的には私は人のリストが好きです... –

答えて

1

私はあなたの第二のコメント

val persons = List[Person[_]](new Student(), new Professor()) 

しかし、私の理解からで可能な代替を自分で述べてきたと信じて、このようなものを行うためのScalaでの慣用の方法は人に型宣言を使用することですそれは学生と教授に定義されています:

trait Person { 
    type PersonImpl <: Person 
    def colleagues: Seq[PersonImpl] 
} 

class Student extends Person { 
    type PersonImpl = Student 
    def colleagues = Seq(this) 
} 

class Professor extends Person { 
    type PersonImpl = Professor 
    def colleagues = Seq(this) 
} 

val persons = List(new Student, new Professor) 

マーティン・オーダーズキーもScalaの言語、そのhe's thinking about unifying type parameters and abstract type membersで述べました。

実際のユースケースに応じて、最も簡単な解決策は、オーバーライドに依存することがあります

trait Person { 
    def colleagues: Seq[Person] 
} 

class Student extends Person { 
    def colleagues: Seq[Student] = Seq(this) 
} 

class Professor extends Person { 
    def colleagues: Seq[Professor] = Seq(this) 
} 

val persons = List(new Student, new Professor)