Scalaに次のクラス/特性があります
trait Write[-T] {
def add(elem : T);
}
class ContraListWrapper[T] (var list : List[T]) extends Write[T] {
def add(elem : T) = {
list = elem :: list
}
}
def bar(list : Write[Number]) = {}
Write トレイトの反変性のおかげで、オブジェクトのリストまたは数値のリストを使用してメソッドを呼び出すことができます。
var list : List[Number] = Nil;
var wlist = new ContraListWrapper(list);
bar(wlist);
var list : List[Object] = Nil;
var wlist = new ContraListWrapper(list);
bar(wlist);
Integer のリストで bar を呼び出すと、Scala でコンパイル エラーが発生します。これは予期されることです。Number のスーパータイプではない整数 (ただし、サブタイプ)
var list : List[Integer ] = new Integer(1) :: Nil;
var wlist = new ContraListWrapper(list);
bar(wlist); //error: type mismatch;
//found : contra.this.ContraListWrapper[Integer]
//required: contra.this.Write[Number]
しかし、整数のリストの変数宣言をインライン化すると、コンパイル エラーがなくなり、動作しているように見えます。(メソッドバーのリストに要素を追加できます)
var list : List[Integer] = new Integer(1) :: Nil;
bar(new ContraListWrapper(list)); //no compile- nor runtime error
編集:太字でRex Kerrへの回答thx
1) これはどのように可能ですか? 最初のタイプの整数が選択され、数値がインライン化されます
2) インライン展開なしではなぜそうならないのですか? Scala は適切な型を取ることができます
3) 実行時エラーが発生しないのはなぜですか? リストは共変であるため
Ps。トレイトとラッパーがなくても、制限付きで反変性を得ることができることはわかっています。