Переопределение членов, имеющих типы, зависящие от пути, в Scala. Требуется пояснение с точки зрения спецификации языка Scala.

Рассмотрим следующий простой эксперимент на Scala:

scala> trait A {class C;val c:C}
defined trait A

scala> object O1 extends A {val c=new C}
defined object O1

scala> object O2 extends A {val c=O1.c}
<console>:9: error: overriding value c in trait A of type O2.C;
 value c has incompatible type
       object O2 extends A {val c=O1.c}

Согласно спецификации языка Scala (SLS 5.1.4):

Тип значения O1.c должен соответствовать типу A.c, потому что первый перекрывает второй.

Вопрос 1:

Где в SLS указано правило, из которого следует, что тип O1.c действительно соответствует типу A.c?

Так почему же object O1 extends A {val c=new C} должен компилироваться в соответствии с SLS?

Вопрос 2:

Где в SLS указано правило, из которого следует, что тип значения O1.c не соответствует типу значения O2.c?

Другими словами, из какого правила SLS следует, что object O2 extends A {val c=O1.c} не должен компилироваться?

Связанный: почему тип значения O2.cbe O2.C согласно SLS?

Обновление:

Каков тип значения O1.c и члена абстрактного значения A.c в соответствии с SLS?


person jhegedus    schedule 08.01.2015    source источник


Ответы (1)


Тип A.c — это A#C, а O1.c (обновление: тип O1.C, который согласно SLS равен O1.type#C) действительно соответствует A#c.

Вопрос 1: внутри O1 тип C — это O1.C, а new C — это new O1.C (см. правила для обозначений типов в 3.2.3). O1.C соответствует O1.C, потому что оно эквивалентно (поскольку эквивалентность — это конгруэнтность).

Вопрос 2: Это следует из того, что O1 не соответствует O2, потому что ни одно из правил в 3.5.1 или 3.5.2 не заставит O1 соответствовать O2. Таким образом, правило для проекций типов в 3.5.2 не применяется.

Вызов конструктора возвращает значение этого типа согласно 5.1.1.

(Я действительно не думаю, что спецификация - лучший способ изучить эти вещи; лучше сначала получить практическое представление о том, как все работает).

person lmm    schedule 08.01.2015
comment
Спасибо за ваш ответ ! Проблема в том, что между «Спецификацией» и почти любой другой книгой по Scala все еще существует огромный разрыв. Спецификацию действительно очень трудно читать, но в таких случаях никакая книга по Scala, написанная для простых смертных, не поможет. - person jhegedus; 08.01.2015
comment
Где я сказал, что A.c это тип? - person jhegedus; 08.01.2015
comment
SLS 3.2.2: проекция типа T#x ссылается на элемент типа с именем x типа T. Таким образом, A#c в данном случае недействителен, поскольку c не является членом типа, поэтому A#c в этом контексте не имеет смысла. Может ли кто-нибудь прокомментировать это? - person jhegedus; 08.01.2015