简体   繁体   English

Scala忽略泛型类型

[英]Scala ignore generic type

I'm trying to avoid to use a generic on Request that contains an optional generic Body to avoid to pass a generic everywhere when it's only needed when writing the body, and also because there's no type when body is not defined: 我试图避免使用包含Request的泛型Body的泛型on Request以避免在仅在编写主体时需要泛型时将泛型传递到任何地方,并且还因为未定义主体时没有类型:

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))
}

The compilation failed with: 编译失败,原因:

Error:(20, 90) type mismatch; 错误:(20,90)类型不匹配;

found : play.api.libs.ws.BodyWritable[(some other)_$1(in value body)] 找到:play.api.libs.ws.BodyWritable [(其他)_ $ 1(在值主体中)]

required: play.api.libs.ws.BodyWritable[_$1(in value body)] 必需:play.api.libs.ws.BodyWritable [_ $ 1(在值主体中)]

I'm wondering if there's a way to not type request. 我想知道是否有一种方法可以不键入请求。

I'm using "com.typesafe.play" %% "play-ws-standalone" % "2.0.4" 我正在使用"com.typesafe.play" %% "play-ws-standalone" % "2.0.4"

In short you cant do this way. 简而言之,您不能这样做。 When wildcard is involved, the type parameter of an expression is always different from others, even they come from the same variable. 涉及通配符时,表达式的类型参数总是彼此不同,即使它们来自同一变量。 The type A body.content and the type parameter A of body.bodyWritable are resolved as different local anonymous types, even though they come from the same variable body , but Scala does not know that, because they are separate expressions. A型body.content和的类型参数body.bodyWritable就被解析成不同的本地匿名类型,即使它们来自同一个变量body ,但斯卡拉不知道,因为它们是独立的表达式。

To resolve this, the most type-safe way (and recommended) is to add type parameter to Request and executeRequest to ensure the type is resolved as the same. 为了解决这个问题,最安全的方法(也是推荐的方法)是在Request和executeRequest中添加类型参数,以确保将类型解析为相同的类型。

You can also create a local method that takes a type parameter to make sure the two expressions shares the same generic type: 您还可以创建一个带有类型参数的本地方法,以确保两个表达式共享相同的通用类型:

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)
}

Alternatively, I sometimes move the calling site into the class where the type parameter is declared, in which the type parameter is guaranteed to be the same. 另外,有时我将调用站点移到声明了type参数的类中,在该类中,保证type参数是相同的。 Something like: 就像是:

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))
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM