Разный вывод типа для `def` и` val` в Scala
Я заметил разницу в выводе типа Scala при применении к def
и val
.
Используя def
, я могу определить абстрактный нулевой метод const
, возвращающий некоторое значение типа Int => Int
. При реализации const
с литералом функции мне не нужно указывать тип параметра, поскольку он может быть выведен компилятором:
trait D {
def const: Int => Int
}
object D extends D {
def const = i => i + 1
}
Это нормально. (С другой стороны, создается новый экземпляр функции для каждого доступа к D.const
.)
Теперь рассмотрим аналогичную конструкцию с использованием val
:
trait V {
val const: Int => Int
}
object V extends V {
val const = i => i + 1
}
Это не будет компилироваться, не с помощью
error: missing parameter type
val const = i => i + 1
^
Почему?
Ответы
Ответ 1
Как и в случае Scala 2.9.1, это "как указано". Ссылаясь на Мартина Одерского из SI-2742:
Для методов возвращаемые типы в унаследованных абстрактных методах берутся как ожидаемый тип правой стороны. Для значений нет такого правила. Так что это будет запрос улучшения спецификации, как я вижу.
Билет имеет низкий приоритет и остается неизменным со времени его первого обсуждения в конце 2009 года, поэтому вряд ли он изменится в ближайшее время.
Ответ 2
Если вы создадите этот код с параметром -Xprint all, вы увидите, что:
abstract trait V extends scala.AnyRef {
<stable> <accessor> def const: Int => Int
};
final object V extends java.lang.Object with V with ScalaObject {
def this(): object V = {
V.super.this();
()
};
private[this] val const: <error> => <error> = ((i: <error>) => i.+(1));
<stable> <accessor> def const: <error> => <error> = V.this.const
}
Таким образом, ошибка возникает при создании private val и accessor.
й компилятор попытается оценить значение, зависящее от val const, прежде чем создать accessor def const.
если вы посмотрите на val const, определенный в признаке, вы увидите, что создание private val было отключено, потому что это только определение для Access-доступа def.
Я думаю, что тип вывода с предыдущим определением (в признаке или суперклассе) произошел только тогда, когда он попытался создать аксессор, а не для оценки значения.
И для последнего def const тип основан только на private [this] val const type: error = > error