我的Scala级别是初学者,我看到了一个明确展示声明implicit request=>
的动作方法。我的问题是我们应该清楚地宣布什么类型的情况?我也看到了不会声明implicit request=>
或request=>
的方法。
有谁可以解释这个优势?
答案 0 :(得分:6)
我不会在scala本身中介绍implicit
的含义,因为它已在stackoverflow here上得到解答。播放文档还解释了request =>
here的使用,但未提供有用的隐式请求的示例。
<强> TL; DR:如有疑问,请使用某些组件可能需要的implicit request
。
如果request
没有改变结果,你的代码块将返回,它可以省略,你可以写。
def myAction = Action { Ok("Hello World") }
另一方面,如果您需要使用请求的内容(标题或正文),则必须添加request
参数。一个常见的例子是解析请求的主体:
Action(parse.json) { request => // it works without implicit
request.body.validate[MyClass].fold(/* do something */)
}
播放文档鼓励我们将请求参数标记为implicit
,因为即使您不直接使用请求,您使用的一个组件也可能需要它作为隐式。如果您在某个操作中遇到隐藏的隐式错误,则可能归结为您忘记隐式提出请求。
我认为你在比赛中可能遇到的一个好例子是internationalization API。总而言之,它允许根据请求中的Accept-Language
标头自动在模板中注入本地化消息。您所要做的就是将I18nSupport
特征添加到控制器并注入messagesApi: MessagesApi
参数(显然定义您的国际化消息)。然后,在您的旋转模板中,您可以使用本地化的消息。例如:
模板:
@()(implicit messages: Messages)
@*
message will be in english, spanish, klingon... depending on the supported
languages and request Accept-Language header
*@
@messages("say-hello")
控制器:
class MyController @Inject() (val messageApi: MessageApi) extends Controller with I18nSupport {
def myAction = Action {implicit request =>
// We do not have to bother about how messages are injected
// The I18nSupport trait does the work for us
Ok(html.myTemplate())
}
}
为了能够做到这一点,I18nSupport
特征包含一个def:
implicit def request2Messages(implicit request: RequestHeader): Messages = /* ... */
它允许自动获取Messages
的实例(编译器将在需要时隐式调用request2Messages(yourRequest)
,但您需要在范围内有一个隐式请求(或请求头)。
我看到的另一个例子是在使用某些安全框架时自动获取操作范围内的用户实例。
这种隐含链的烦人问题在于,如果您忘记隐式提出请求,编译器可能会抱怨范围内缺少隐式Messages
,而实际问题是缺少隐式请求。 / p>
答案 1 :(得分:2)
implicit
有许多用例 - 其中一个是隐式地将参数传递给定义隐式参数的函数。
例如:
def withImplicitParameter(greeting: String)(implicit name: String): Unit = {
println(greeting + " " + name)
}
// Using implicits
implicit val name = "Bob"
withImplicitParameter("Hello") // "Bob" is passed in implicitly for name parameter. Prints "Hello Bob"
withImplicitParameter("Bye")("Joe") // "Joe" is passed in explicitly for name parameter. Prints "Bye Joe"
因此,除非您调用的其中一个函数具有Request
类型的隐式参数,否则您不需要{ implicit request => ... }
答案 2 :(得分:0)
另一个使用类似的API播放implicit req => ...
的示例
case class ClassName(name: String)
def log(msg: String)(implicit className: ClassName) =
System.out.println(s"message=`$msg` className=`${className.name}`")
val cls = Option(ClassName("ImplicitClass"))
cls.foreach { implicit name =>
log("explicit message")
}
生产
message=`explicit message` className=`ImplicitClass`