Ключевое слово implicit в scala - это повод для споров и обсуждений, это инструмент, позволяющий увеличить гибкость и читаемость кода в разы, да и просто безумно интересная фича, давайте же разберёмся что это такое, implicits?
Существует несколько видов implicit'ов, начнём по порядку:
Первый вид - неявные значения, то есть implicit val. Предположим, у нас есть метод:
def implEx()(implicit a: String) = println(a)
, то обозначив implicit val myString = "Hello implicit" в скоупе видимости, мы сможем вызвать implEx() - как видите, мы не передаём туда значение "а", оно подтягивается автоматически(со String пример исключительно показательный, используйте имплиситы исключительно со своими созданными классами и типами - во избежание проблем и зудящей боли одного места). Что же такое "скоуп видимости"?
Как же значения имплиситов подтягиваются сами, без вашего участия? Ну тут я немного наврал, не сами, это компилятор делает за вас всю грязную работу. И для того, чтобы он знал, где искать необходимый имплисит для функции, и существует такое понятие как скоуп видимости. Компилятор ищет их внутри тела метода, внутри класса, которому принадлежит метод, затем смотрит в импортах, и, наконец, в объекте-компаньоне. Если не найдёт - будет ругаться, и Вы ничего не скомпилируете.
Давайте дальше, второй тип - неявные преобразования.Посмотрим:
implicit def toInt(s:String) = s.toInt
def printIntX2(i:Int) = println(i*2)
printIntX2("2")
Что же тут происходит? Метод toInt - это неявное преобразование, implicit видите в начале? И так, метод printIntX2 - принимает входящим значением Int, умножает его на 2 и выводит на экран что вышло. Однако мы его вызываем, ставя в качестве аргумента строку "2", почему всё работает? Потому, что выше - наше преобразование. Компилятор видит, что что-то в методе не сходится, и смотрит в скоуп в поисках помощи, и находит её!
Кстати, необходимо дополнить, что при обнаружении двух конфликтующих имплиситов в скоупе у Вас будут проблемы, поэтому будьте осторожны!
Третий тип, мой любимый: неявные классы! Бывало ли такое, что у Вас появилась необходимость расширить класс, добавить в него новые методы, например, а писать обёртку и использовать её не хочется? Вот тут и поможет неявный класс:
implicit class helper(s:String){
def x2 = s + s
}
println("hello ".x2)
В неявном классе есть условие: обязательно должен быть конструктор с только 1 аргументом - то, что он расширяет. В данном случае мы расширили стринг, и добавили в неё метод, дублирующий содержимое ещё раз(вывод будет hello hello ) - и далее можем обращаться к этому методу, как к любому другому родному методу стринга!
Это лишь пара небольших примеров использования implicits, но их применение, особенно в умелых руках, может творить чудеса!