1

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。トレイトとラッパーがなくても、制限付きで反変性を得ることができることはわかっています。

4

1 に答える 1

3

Listは共変なのでList[Number]、 のスーパータイプですList[Integer]。2 番目のケースでは、Scala はコードを見て、「bar は Number で型付けされた何かを望んでいるので、それContraListWrapperを返すことができるかどうか見てみましょう。確かにできます。aList[Number]ではなくa を取得していることがわかりますList[Integer]。 "

最初のケースでは、タイプはすでに固定されています。

2番目のケースを次のように変更することで、これを自分で実証できます

bar(new ContraListWrapper[Integer](list));

コンパイラは自由にタイプを として選択できないため、これは当然のことながらコンパイル時エラーを発生させますNumber

于 2010-09-07T14:24:10.600 に答える