2010-09-07 1 views
1

У меня есть следующие классы/черты в ScalaMissing компиляции ошибка/выполнения, когда встраивание

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]) = {} 

Вызов метода с список объектов или список номеров, работ, благодаря контрвариации от записи признака.

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, я получаю ошибку компиляции в Scala. Это ожидается; Целое не супертипом номер (но подтипа)

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, исчезла ошибка компиляции, и даже, кажется, работает. (Я добавил элемент списка в методе бар)

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

Edit: ответы на ТНХ Rex Керр в смелой

1) Как ему это возможно? Первый тип Целое число выбрано, с инкрустацией Номер

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

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

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

ответ

3

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

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

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

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

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

Смежные вопросы