Scala中的重要问题

时间:2015-05-15 10:18:00

标签: scala

我会让代码发言:

import scala.concurrent.Future

trait SomeRequest
trait SomeResponse
trait ApiStandard {
  def apiCall[Req <: SomeRequest, Resp <: SomeResponse](request: Req): Future[Resp]
}

case class XXRequest() extends SomeRequest
case class XXResponse() extends SomeResponse
class XXStandard extends ApiStandard {
  override def apiCall(request: XXRequest): Future[XXResponse] = ???
}

基本上我有几个数据特征(SomeRequest,SomeResponse)和行为特征ApiStandard。还有案例类XXRequest和XXResponse覆盖数据特征。我正在尝试创建一个名为XXStandard的ApiStandard的具体实现。但它在语法上并不正确。作为斯卡拉初学者,我无法理解为什么。

请稍微说清楚。

感谢。

2 个答案:

答案 0 :(得分:4)

ApiStandard定义了一种方法apiCall,它接受​​的参数比XXStandard提供的参数更灵活。

为了说明,

如果你有

val something: ApiStandard = ???

你知道你可以打电话

val req: SomeRequest
something(req)

如果???可能是new XXStandard()XXStandard只接受XXRequest作为apiCall的参数,那么这将被破坏:没有办法知道req实际上是XXRequest,事实上,它不一定是一个。

幸运的是,这不会编译,因为apiCall中的XXStandard无法实现ApiStandard.apiCall

要使XXStandard成为可以作为ApiStandard子类型的东西,XXStandard中的apiCall必须采用您在特征中声明的类型,或者作为其参数的超类型。

TL; DR:

方法的参数类型是逆变的。

答案 1 :(得分:1)

您对apiCall的定义表明它必须适用于任何Req <: SomeRequestResp <: SomeResponse,因此调用者可以像(例如)apiCall[MyReq, SomeoneElsesResp](new MyReq)一样调用它。但XXStandard中的实施并不像这样;它只支持单个请求和响应类型。假设你想要的是什么,你需要将类型参数移到ApiStandard

trait ApiStandard[Req <: SomeRequest, Resp <: SomeResponse] {
  def apiCall(request: Req): Future[Resp]
}

class XXStandard extends ApiStandard[XXRequest, XXResponse] {
  override def apiCall(request: XXRequest): Future[XXResponse] = ???
}