我正在阅读 Scala playframework 教程,我遇到了这段让我感到困惑的代码片段:
def newTask = Action { implicit request => taskForm.bindFromRequest.fold( errors => BadRequest(views.html.index(Task.all(), errors)), label => { Task.create(label) Redirect(routes.Application.tasks()) } ) }
所以我决定调查并遇到这个帖子。
我还是不明白。
这有什么区别:
implicit def double2Int(d : Double) : Int = d.toInt
和
def double2IntNonImplicit(d : Double) : Int = d.toInt
除了显而易见的事实之外,它们具有不同的方法名称。
我应该什么时候使用implicit,为什么?
implicit
我将在下面解释隐式的主要用例,但更多详细信息请参见Programming in Scala 的相关章节。
隐式参数
方法的最终参数列表可以标记为implicit,这意味着值将从调用它们的上下文中获取。如果范围内没有正确类型的隐式值,则不会编译。由于隐式值必须解析为单个值并避免冲突,因此最好使类型特定于其用途,例如,不要求您的方法找到隐式Int!
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允许它进行类型检查的类型的隐式值。因此,如果A需要 an 并且它找到 a B,它将B => A在范围内查找类型的隐式值(它还会检查其他一些地方,比如在B和A伴随对象中,如果它们存在的话)。由于defs 可以“扩展”为Function对象,因此 animplicit def xyz(arg: B): A也可以。
Function
A
B
B => A
def
implicit def xyz(arg: B): A
因此,您的方法之间的区别在于,当找到 a 但需要 animplicit时,编译器将为您插入标记的方法。Double``Int
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)
在第二个中,我们手动插入了转换;首先,编译器会自动执行相同的操作。由于左侧的类型注释,需要进行转换。
关于您在 Play 中的第一个片段:
此页面上的操作说明来自 Play 文档(另请参阅API 文档)。您正在使用
apply(block: (Request[AnyContent]) 鈬� Result): Action[AnyContent]
在Action对象上(这是同名特征的伴侣)。
Action
所以我们需要提供一个函数作为参数,它可以写成如下形式的文字
request => ...
在函数字面量中,前面的部分=>是值声明,可以根据需要进行标记implicit,就像在任何其他val声明中一样。在这里,request 不必implicit为 this 进行类型检查,但通过这样做,它 可以作为函数中可能需要它的任何方法的隐式值 使用(当然,它也可以显式使用). 在这种特殊情况下,这样做是因为FormbindFromRequest类上的方法需要一个隐式参数。Request
=>
val
request
bindFromRequest
Request