Компилятор Scala часто может вывести тип выражения, так что вам не нужно указывать его явным образом.
Не указывая тип
val businessName = "Montreux Jazz Café"
Компилятор может определить, что тип константы businessName
является String
. Аналогичным образом это работает и для методов:
def squareOf(x: Int) = x * x
Компилятор может определить, что возвращаемый тип является Int
, поэтому явного указания типа не требуется.
Для рекурсивных методов компилятор не в состоянии вывести тип. Вот программа, которая не скомпилируется по этой причине:
def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1)
def fac(n: Int) = if n == 0 then 1 else n * fac(n - 1)
Также необязательно указывать параметры типа при вызове полиморфных методов или обобщенных классов. Компилятор Scala определит тип параметра из контекста и из типов фактически передаваемых параметров метода/конструктора.
Вот два примера:
case class MyPair[A, B](x: A, y: B)
val p = MyPair(1, "scala") // тип: MyPair[Int, String]
def id[T](x: T) = x
val q = id(1) // тип: Int
Компилятор использует типы аргументов MyPair
для определения типа A
и B
. Тоже самое для типа x
.
Параметры
Для параметров компилятор никогда не выводит тип. Однако, в некоторых случаях, он может вывести типы для параметров анонимной функции при передаче ее в качестве аргумента.
Seq(1, 3, 4).map(x => x * 2) // List(2, 6, 8)
Параметр у map - f: A => B
(функциональный параметр переводящий тип из A в B). Поскольку мы разместили целые числа в нашей последовательности Seq
, компилятор знает, что элемент A
является Int
(т.е. x
является целым числом). Поэтому компилятор может определить из выражения x * 2
, что результат (B
) является типом Int
.
Когда не следует полагаться на выведение типа
Обычно считается, наиболее удобочитаемым объявить тип членов, которые открыты для публичного использования через API. Поэтому мы рекомендуем вам явно указывать тип для любых API, которые будут доступны пользователям вашего кода.
Кроме того, выведение может иногда приводить к слишком специфичному типу. Предположим, мы напишем:
var obj = null
Тогда мы не сможем далее сделать это переназначение:
obj = new AnyRef
Такое не будет компилироваться, потому что для obj
предполагался тип Null
. Поскольку единственным значением этого типа является null
, то невозможно присвоить другое значение.
Contributors to this page:
Contents
- Введение
- Основы
- Единобразие типов
- Классы
- Значения Параметров По умолчанию
- Именованные Аргументы
- Трейты
- Кортежи
- Композиция классов с трейтами
- Функции Высшего Порядка
- Вложенные Методы
- Множественные списки параметров (Каррирование)
- Классы Образцы
- Сопоставление с примером
- Объекты Одиночки
- Регулярные Выражения
- Объект Экстрактор
- Сложные for-выражения
- Обобщенные Классы
- Вариантность
- Верхнее Ограничение Типа
- Нижнее Ограничение Типа
- Внутренние классы
- Члены Абстрактного Типа
- Составные Типы
- Самоописываемые типы
- Контекстные параметры, также известные, как неявные параметры
- Неявные Преобразования
- Полиморфные методы
- Выведение Типа
- Операторы
- Вызов по имени
- Аннотации
- Пакеты и Импорт
- Объекты Пакета