Scala 忽略泛型类型
Scala ignore generic type
我试图避免在 Request
上使用包含可选泛型 Body
的泛型,以避免仅在编写正文时才需要时在任何地方传递泛型,也因为未定义主体时没有类型:
case class Body[A](content: A)(implicit val bodyWritable: BodyWritable[A])
case class Request(url: String, body: Option[Body[_]])
private def executeRequest(request: Request) = {
val wsClient: StandaloneWSClient = ???
val requestWithUrl = wsClient.url(request.url)
request.body.fold(requestWithUrl)(body => requestWithUrl.withBody(body.content)(body.bodyWritable))
}
编译失败:
Error:(20, 90) type mismatch;
found : play.api.libs.ws.BodyWritable[(some other)_(in value body)]
required: play.api.libs.ws.BodyWritable[_(in value body)]
我想知道是否有办法不输入请求。
我正在使用 "com.typesafe.play" %% "play-ws-standalone" % "2.0.4"
总之你不能这样做。当涉及通配符时,表达式的类型参数总是与其他类型参数不同,即使它们来自同一个变量。类型 A body.content
和 body.bodyWritable
的类型参数 A 被解析为不同的本地匿名类型,即使它们来自同一个变量 body
,但 Scala 不知道这一点,因为它们是单独的表达式。
要解决此问题,最类型安全的方法(也是推荐的方法)是将类型参数添加到 Request 和 executeRequest 以确保类型被解析为相同。
您还可以创建一个采用类型参数的本地方法,以确保两个表达式共享相同的泛型类型:
private def executeRequest(request: Request) = {
val wsClient: StandaloneWSClient = ???
val requestWithUrl = wsClient.url(request.url)
def f[A](body: Body[A]) = requestWithUrl.withBody(body.content)(body.bodyWritable)
request.body.fold(requestWithUrl)(body => f(body)) // or shorten to request.body.fold(requestWithUrl)(f)
}
或者,我有时会将调用站点移到声明类型参数的class 中,保证类型参数相同。类似于:
case class Body[A](content: A)(implicit val bodyWritable: BodyWritable[A]) {
def getRequest(req: WSRequest) = req.withBody(content)
}
case class Request(url: String, body: Option[Body[_]])
private def executeRequest(request: Request) = {
val wsClient: StandaloneWSClient = ???
val requestWithUrl = wsClient.url(request.url)
request.body.fold(requestWithUrl)(body => body.getRequest(requestWithUrl))
}
我试图避免在 Request
上使用包含可选泛型 Body
的泛型,以避免仅在编写正文时才需要时在任何地方传递泛型,也因为未定义主体时没有类型:
case class Body[A](content: A)(implicit val bodyWritable: BodyWritable[A])
case class Request(url: String, body: Option[Body[_]])
private def executeRequest(request: Request) = {
val wsClient: StandaloneWSClient = ???
val requestWithUrl = wsClient.url(request.url)
request.body.fold(requestWithUrl)(body => requestWithUrl.withBody(body.content)(body.bodyWritable))
}
编译失败:
Error:(20, 90) type mismatch;
found : play.api.libs.ws.BodyWritable[(some other)_(in value body)]
required: play.api.libs.ws.BodyWritable[_(in value body)]
我想知道是否有办法不输入请求。
我正在使用 "com.typesafe.play" %% "play-ws-standalone" % "2.0.4"
总之你不能这样做。当涉及通配符时,表达式的类型参数总是与其他类型参数不同,即使它们来自同一个变量。类型 A body.content
和 body.bodyWritable
的类型参数 A 被解析为不同的本地匿名类型,即使它们来自同一个变量 body
,但 Scala 不知道这一点,因为它们是单独的表达式。
要解决此问题,最类型安全的方法(也是推荐的方法)是将类型参数添加到 Request 和 executeRequest 以确保类型被解析为相同。
您还可以创建一个采用类型参数的本地方法,以确保两个表达式共享相同的泛型类型:
private def executeRequest(request: Request) = {
val wsClient: StandaloneWSClient = ???
val requestWithUrl = wsClient.url(request.url)
def f[A](body: Body[A]) = requestWithUrl.withBody(body.content)(body.bodyWritable)
request.body.fold(requestWithUrl)(body => f(body)) // or shorten to request.body.fold(requestWithUrl)(f)
}
或者,我有时会将调用站点移到声明类型参数的class 中,保证类型参数相同。类似于:
case class Body[A](content: A)(implicit val bodyWritable: BodyWritable[A]) {
def getRequest(req: WSRequest) = req.withBody(content)
}
case class Request(url: String, body: Option[Body[_]])
private def executeRequest(request: Request) = {
val wsClient: StandaloneWSClient = ???
val requestWithUrl = wsClient.url(request.url)
request.body.fold(requestWithUrl)(body => body.getRequest(requestWithUrl))
}