Отсутствует ошибка компиляции / выполнения при вставке - PullRequest
1 голос
/ 07 сентября 2010

У меня есть следующие классы / черты в 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]) = {}

Вызов метода с помощью List of Object или списка чисел работает благодаря контрастности черты 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);

Когда я вызываю bar со списком Integer, я получаю ошибку компиляции в Scala.Это ожидается;Integer, а не супертип 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]

Но когда я встраиваю объявление переменной в список Integer, ошибка компиляции исчезает, и она даже кажется работающей.(Я могу добавить элемент в список в методе bar )

var list : List[Integer] = new Integer(1) :: Nil;
bar(new ContraListWrapper(list)); //no compile- nor runtime error 

Редактировать: thx отвечает Рексу Керру полужирный

1) Как это возможно? Первый тип Integer выбран с номером вставки

2) Почему это не так без вставки? Scala может принимать соответствующий тип

3) Почему я не получаю событие, получающее ошибку времени выполнения? Поскольку списки ковариантны

Ps.Я знаю, что могу получить контравариантность без черты и обертки, и с привязкой.

1 Ответ

3 голосов
/ 07 сентября 2010

List является ковариантным, поэтому List[Number] является супертипом List[Integer].Во втором случае Scala смотрит на код и говорит: «Ха, bar хочет что-то, набранное с помощью Number, поэтому давайте посмотрим, сможем ли мы получить ContraListWrapper, чтобы вернуть это. Конечно, мы можем - мы можем сказать, что получим1005 * вместо List[Integer]. "

В первом случае тип уже зафиксирован.

Вы можете продемонстрировать это себе, изменив второй случай на

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

Это дает ошибку времени компиляции, как и должно быть, потому что компилятор не может выбрать тип как Number.

...