19章の後半の変位指定アノテーションのあたりから難しい。
クラスを宣言するトップレベルのポジションは陽性に分類されるとある。ネストの中のポジションはディフォルトではそれを囲む部分と同じだが、変化する例外がある。それは、メソッドの値パラメーターのポジションでは、メソッドの外のポジションの分類が反転するとある。メソッドの型パラメーターのポジションでも反転すると言っている。
P370でQueue[T]の定義で、Tがenqueueメソッドのパラメーターの型として現れる。Tが現れるその位置は陰性ポジションなので、、、とあるが、ここがよく理解できない。
なお、リスト19.4参照とあるが、19.1のこと?だろうか
class Queue[T]{
----------------
def enqueue(x: T) =
new Queue(leading, x :: trailing)
}
※おおざっぱにいって、戻り値なら、共変(陽性)とするが
引数なら、反変(陰性)となるということなんだろうか?
そこで、少しもどってP365のリスト19.5が次のような場合を考える
class Cell[+T](init:T){
private[this] var current = init
def get = current
def set(x:T){current =x}
これが、もしコンパイルできたとする。(実際はできないが)
val c1=new Cell[String]("abc")
val c2:Cell[Any]=c1 ←Cellは共変なので、これはOK
c2.set(1)
val s:String=c1.get
となり、コードの型に矛盾はないものの、String型の変数にInt型の値を代入することとなり、エラーとなる。
P372で、さらに具体例で、※の部分を説明している。
リスト19.8の
trait Function1[-S,+T] { 云々 }
の意味するところは、Sが反変、Tが共変 そして S =>T なる形の関数を展開したものらしい。
そしてリスト19.9で
info :Book => AnyRefには、Publication=>Stringの関数が使われている。
引数は Book extends Publication Sのほう
戻り値は String extends AnyRef Tのほう
ということで 矛盾ない構成になっている感じはする。ん~、ややこしい。
0 件のコメント:
コメントを投稿