Метод может иметь список контекстных параметров (contextual parameters),
также называемых неявными параметрами (implicit parameters) или, точнее, имплицитами (implicits).
Списки параметров, начинающиеся с ключевого слова using
(или implicit
в Scala 2), задают контекстные параметры.
Если сторона вызова явно не предоставляет аргументы для таких параметров,
Scala будет искать неявно доступные given
(или implicit
в Scala 2) значения правильного типа.
Если можно найти подходящие значения, то они автоматически передаются.
Лучше всего вначале показать это на небольшом примере.
Мы определяем интерфейс Comparator[A]
, который может сравнивать элементы типа A
,
и предоставляем две реализации для Int
-ов и String
-ов.
Затем мы определяем метод max[A](x: A, y: A)
, который возвращает больший из двух аргументов.
Так как x
и y
имеют абстрактный тип, в общем случае мы не знаем, как их сравнивать, но можем запросить соответствующий компаратор.
Поскольку обычно для любого заданного типа существует канонический компаратор A
,
то мы можем объявить их как заданные (given) или неявно (implicitly) доступные.
trait Comparator[A] {
def compare(x: A, y: A): Int
}
object Comparator {
implicit object IntComparator extends Comparator[Int] {
def compare(x: Int, y: Int): Int = Integer.compare(x, y)
}
implicit object StringComparator extends Comparator[String] {
def compare(x: String, y: String): Int = x.compareTo(y)
}
}
def max[A](x: A, y: A)(implicit comparator: Comparator[A]): A =
if (comparator.compare(x, y) >= 0) x
else y
println(max(10, 6)) // 10
println(max("hello", "world")) // world
// не компилируется:
println(max(false, true))
// ^
// error: could not find implicit value for parameter comparator: Comparator[Boolean]
Параметр comparator
автоматически заполняется значением Comparator.IntComparator
для max(10, 6)
и Comparator.StringComparator
для max("hello", "world")
.
Поскольку нельзя найти неявный Comparator[Boolean]
, вызов max(false, true)
не компилируется.
trait Comparator[A]:
def compare(x: A, y: A): Int
object Comparator:
given Comparator[Int] with
def compare(x: Int, y: Int): Int = Integer.compare(x, y)
given Comparator[String] with
def compare(x: String, y: String): Int = x.compareTo(y)
end Comparator
def max[A](x: A, y: A)(using comparator: Comparator[A]): A =
if comparator.compare(x, y) >= 0 then x
else y
println(max(10, 6)) // 10
println(max("hello", "world")) // world
// не компилируется:
println(max(false, true))
-- Error: ----------------------------------------------------------------------
1 |println(max(false, true))
| ^
|no given instance of type Comparator[Boolean] was found for parameter comparator of method max
Параметр comparator
автоматически заполняется значением given Comparator[Int]
для max(10, 6)
и given Comparator[String]
для max("hello", "world")
.
Поскольку нельзя найти given Comparator[Boolean]
, вызов max(false, true)
не компилируется.
Места, где Scala будет искать эти параметры, делятся на две категории:
- Вначале Scala будет искать
given
параметры, доступ к которым можно получить напрямую (без префикса) в месте вызоваmax
. - Затем он ищет членов, помеченных как given/implicit во всех объектах компаньонах,
связанных с типом неявного параметра (например:
object Comparator
для типа-кандидатаComparator[Int]
).
Более подробное руководство, о том где scala ищет неявные значения можно найти в FAQ
Contributors to this page:
Contents
- Введение
- Основы
- Единобразие типов
- Классы
- Значения Параметров По умолчанию
- Именованные Аргументы
- Трейты
- Кортежи
- Композиция классов с трейтами
- Функции Высшего Порядка
- Вложенные Методы
- Множественные списки параметров (Каррирование)
- Классы Образцы
- Сопоставление с примером
- Объекты Одиночки
- Регулярные Выражения
- Объект Экстрактор
- Сложные for-выражения
- Обобщенные Классы
- Вариантность
- Верхнее Ограничение Типа
- Нижнее Ограничение Типа
- Внутренние классы
- Члены Абстрактного Типа
- Составные Типы
- Самоописываемые типы
- Контекстные параметры, также известные, как неявные параметры
- Неявные Преобразования
- Полиморфные методы
- Выведение Типа
- Операторы
- Вызов по имени
- Аннотации
- Пакеты и Импорт
- Объекты Пакета