Я объясню основные случаи использования имплицитов ниже, но более подробно см. relevant chapter of Programming in Scala.
Неявных параметры
Окончательный список параметров по методе могут быть отмечены implicit
, что означает, что значения будут взяты из контекста, в котором они называются. Если в сфере видимости нет значения неявного значения, он не будет компилироваться. Поскольку неявное значение должно быть разрешено к одному значению и избегать столкновений, целесообразно сделать тип специфичным для своей цели, например. не требуйте, чтобы ваши методы нашли неявный Int
!
пример:
// probably in a library
class Prefixer(val prefix: String)
def addPrefix(s: String)(implicit p: Prefixer) = p.prefix + s
// then probably in your application
implicit val myImplicitPrefixer = new Prefixer("***")
addPrefix("abc") // returns "***abc"
Неявные преобразования
Когда компилятор находит выражение неправильного типа для контекста, он будет искать неявное Function
значения такого типа, который позволит его к typecheck. Поэтому, если требуется A
, и он найдет B
, он будет искать неявное значение типа B => A
в области видимости (он также проверяет некоторые другие места, например, в сопутствующих объектах и A
, если они существуют). Так как def
s могут быть «eta-extended» в Function
объектах, то и implicit def xyz(arg: B): A
.
Таким образом, разница между вашими методами заключается в том, что один из отмеченных implicit
будет вставлен вам компилятором, когда будет найден Double
, но требуется Int
.
implicit def doubleToInt(d: Double) = d.toInt
val x: Int = 42.0
будет работать так же, как
def doubleToInt(d: Double) = d.toInt
val x: Int = doubleToInt(42.0)
Во втором мы вставили преобразование вручную; в первом компилятор сделал то же самое автоматически. Преобразование требуется из-за аннотации типа с левой стороны.
Что касается вашего первого фрагмента из игры:
действия объясняются на this page из документации Play (также см API docs). Вы используете
apply(block: (Request[AnyContent]) ⇒ Result): Action[AnyContent]
на Action
объекта (который является спутником признака того же имени).
Таким образом, мы должны предоставить функции в качестве аргумента, который может быть записан в виде литерала в виде
request => ...
В функции буквального, часть перед =>
является декларацией значение, и может быть пометьте implicit
, если хотите, как и в любой другой декларации val
. Здесь не имеет для этого, чтобы ввести тип проверки, но при этом будет доступным как неявное значение для любых методов, которые могут понадобиться ему в пределах функции (и, конечно, это может также будет использоваться явно). В этом конкретном случае это было сделано, потому что метод bindFromRequest
класса Form требует неявного аргумента Request
.
Благодарим за отзыв. Ссылка на главу 21 действительно потрясающая. Ценить это. – Clive
Чтобы добавить это, следующее видео дает отличное объяснение имплицитов плюс некоторые другие особенности scala. Http://www.youtube.com/watch?v=IobLWVuD-CQ – Shakti