Неявные (implicit) параметры и преобразования в Scala

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

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Пробежавшись по предыдущим статьям на Хабре, тыц и тыц так и не удалось в быстром режиме понять, что делает неявность (implicit) в Scala. Попробуем разобраться вместе.


Итак, implicit в Scala позволяют избежать вызывания методов или явных ссылок на переменные, и взамен этого позволяют компилятору самому найти нужные неявные данные.

Например, мы могли бы написать функцию для преобразования из Float в Int(FloatToInt) и, вместо того, чтобы вызвать эту функцию явно, компилятор бы сделал это вместо нас неявно:

def double(value: Int) = value * 2
implicit def FloatToInt(value: Float):Int = value.toInt
println(double(2.5F))

Запутанно? Давайте обо всём по порядку.

Итак, сегодня мы рассмотрим две категории implicit, а именно:

  • Неявные параметры (implicit parameters, values). Они являются автоматически переданными компилятором значениями, объявленными через implicit.
  • Неявное преобразование (implicit conversion). При несовпадении типа ожидаемого параметра с входящим параметром компилятор ищет любой метод в области видимости, отмеченный implicit и с нужными в данной ситуации ожидаемым параметром и входящим параметром и автоматически его передаёт.

Неявный параметр


Неявный параметр — это параметр функции, которому предшествует ключевое слово implicit. Оно значит, что, если не передано никакого значения при вызове функции, то компилятор собственноручно будет искать неявный параметр и передаст его за нас.

Например, такая функция, принимающая на вход неявный параметр value и удваивающая его:

def double(implicit value: Int) = value * 2

Без неявного параметра упадёт с ошибкой:

def double(implicit value: Int) = value * 2
println(double) // error: could not find implicit value for parameter value

С переданным явно параметром сработает:

def double(implicit value: Int) = value * 2
println(double(3))  // 6

С неявным параметром это будет выглядеть так:

def double(implicit value: Int) = value * 2
implicit val multiplier = 2
println(double) // 4

Но нужно быть аккуратным:

def double(implicit value: Int) = value * 2
implicit val multiplier = 2
implicit val multiplier2 = 1 
println(double) // error: ambiguous implicit values

И напоследок пример с передачей в качестве неявного параметра def:

def double(implicit value: Int) = value * 2
val cappucinoLarge: Boolean = false
implicit def cappucinoPrice: Int = if (cappucinoLarge) 200 else 100
println(double) // 200

Т.е. в итоге у нас получится
double(cappucinoPrice())

Примечания по синтаксису:


def func1(implicit value1: Int)                          // value1 неявно
def func2(implicit value1: Int, value2: Int)             // value1 и value2 неявны
def func3(value1: Int, implicit value2: Int)             // ошибка компиляции
def func4(value1: Int)(implicit value2: Int)             // только value2 неявно
def func5(implicit value1: Int)(value2: Int)             // ошибка компиляции
def func6(implicit value1: Int)(implicit value2: Int)    // ошибка компиляции

Неявное преобразование


Возвращаясь к примеру из Float в Int:

def double(value: Int) = value * 2
implicit def FloatToInt(value: Float):Int = value.toInt
println(double(2.5F))

При вызове double у нас происходит несовпадение типа ожидаемого параметра (Int) с входящим параметром (Float). Поэтому компилятор ищет любой метод в области видимости, отмеченный implicit и с нужными в данной ситуации ожидаемым параметром (Int) и входящим параметром (Float). Находит FloatToInt, производит преобразование и передает дальше нужное значение в double.

Теперь, надеюсь, стало понятнее. Всем успехов в освоении Scala!
Источник: https://habr.com/ru/post/451358/


Интересные статьи

Интересные статьи

В этой статье мы рассмотрим, как система управления 1С-Битрикс справляется с большими нагрузками. Данный вопрос особенно актуален сегодня, когда электронная торговля начинает конкурировать по обороту ...
Привет, Хабр. Сегодня мы предлагаем вам перевод статьи, затрагивающей не самую обсуждаемую тему: компиляцию кода в Python, а именно: работу с абстрактным синтаксическим деревом (AST) и байт-ко...
VUE.JS - это javascript фрэймворк, с версии 18.5 его добавили в ядро битрикса, поэтому можно его использовать из коробки.
Сравнивать CRM системы – дело неблагодарное. Очень уж сильно они отличаются в целях создания, реализации, в деталях.
В Челябинске проходят митапы системных администраторов Sysadminka, и на последнем из них я делал доклад о нашем решении для работы приложений на 1С-Битрикс в Kubernetes. Битрикс, Kubernetes, Сep...