7za*_*rk7 6 scala pattern-matching case-class extractor
我正在尝试将REST API的响应建模为案例类,我可以使用模式匹配.
我认为这是一个很好的假设继承,但我看到这是不赞成的.我知道已经存在与案例类和继承相关的问题,但我的问题更多的是关于如何在没有继承的情况下在这里建模"正确的方法" .
我从以下两个案例类开始,它们工作正常:
case class Body(contentType: String, content: String)
case class Response(statusCode: Int, body: Body)
Run Code Online (Sandbox Code Playgroud)
即REST调用将返回类似于:
Response(200, Body("application/json", """{ "foo": "bar" }"""))
Run Code Online (Sandbox Code Playgroud)
我可以模仿匹配,如:
response match {
case Response(200, Body("application/json", json)) => println(json)
case Response(200, Body("text/xml", xml)) => println(xml)
case Response(_,_) => println("Something unexpected")
}
Run Code Online (Sandbox Code Playgroud)
等工作正常.
我遇到麻烦的地方是:我想要这些案例类的帮助扩展,例如:
case class OK(body: Body) extends Response(200, body)
case class NotFound() extends Response(404, Body("text/plain", "Not Found"))
case class JSON(json: String) extends Body("application/json", json)
case class XML(xml: String) extends Body("text/xml", xml)
Run Code Online (Sandbox Code Playgroud)
所以我可以做这样的简化模式匹配:
response match {
case OK(JSON(json)) => println(json)
case OK(XML(xml)) => println(xml)
case NotFound() => println("Something is not there")
// And still drop down to this if necessary:
case Response(302, _) => println("It moved")
}
Run Code Online (Sandbox Code Playgroud)
并且还允许我的REST代码直接使用和返回:
Response(code, Body(contentType, content))
Run Code Online (Sandbox Code Playgroud)
这更容易动态地构建响应.
所以...
我可以通过以下方式编译(使用弃用警告):
case class OK(override val body: Body) extends Response(200, body)
Run Code Online (Sandbox Code Playgroud)
但是,这似乎不适用于模式匹配.
Response(200, Body("application/json", "")) match {
case OK(_) => ":-)"
case _ => ":-("
}
res0: java.lang.String = :-(
Run Code Online (Sandbox Code Playgroud)
关于这如何工作的任何想法?我对不同的方法持开放态度,但这是我试图找到案例类的实际用途
0__*_*0__ 10
案例类不应该被子类化有几个原因.在你的情况下,问题变成了OK
另一种类型而不是(子类型)Response
,因此匹配失败(即使参数匹配,类型也不匹配).
您将需要自定义提取器.例如:
case class Response(code: Int, body: String)
object OK {
def apply(body: String) = Response(200, body)
def unapply(m: Response): Option[String] = m match {
case Response(200, body) => Some(body)
case _ => None
}
}
def test(m: Response): String = m match {
case OK(_) => ":-)"
case _ => ":-("
}
test(Response(300, "Hallo")) // :-(
test(Response(200, "Welt")) // :-)
test(OK("Welt")) // :-)
Run Code Online (Sandbox Code Playgroud)
此线程中有更多自定义提取器的示例.
归档时间: |
|
查看次数: |
1663 次 |
最近记录: |