Scala 类型 : How to Restrict the Generic Type of a Subclass?

标签 scala generics types bounds

我有一个特点:

trait OAuthService {
  def sendWithAuthorizationQueryParams[A](request: OAuthRequest)(implicit unmarshaller: Unmarshaller[ResponseEntity, A]): Future[A] = {
    val httpRequest = request.toHttpRequestWithAuthorizationQueryParams

    sendAndReceive(httpRequest, request.signature)
  }

  def sendWithAuthorizationHeader[A](request: OAuthRequest)(implicit unmarshaller: Unmarshaller[ResponseEntity, A]): Future[A] = {
    val httpRequest = request.toHttpRequestWithAuthorizationHeader

    sendAndReceive(httpRequest, request.signature)
  }

  protected def sendAndReceive[A](httpRequest: HttpRequest, id: String)(implicit unmarshaller: Unmarshaller[ResponseEntity, A]): Future[A]
}

我正在创建一个子类:

class StreamingOAuthService()(implicit val actorPlumbing: ActorPlumbing) extends OAuthService {
  private val log = LoggerFactory.getLogger(getClass())

  override protected def sendAndReceive[A](httpRequest: HttpRequest, id: String)(implicit unmarshaller: Unmarshaller[ResponseEntity, A]) = {
    log.debug(s"Http request: {}.", httpRequest)

    import actorPlumbing._

    val host = httpRequest.uri.authority.host.address()

    val connectionFlow: Flow[HttpRequest, HttpResponse, Future[OutgoingConnection]] = Http().outgoingConnectionTls(host)

    Source.single(httpRequest)
      .via(connectionFlow)
      .runWith(Sink.head)
  }
}

StreamingOAuthService中,我想将泛型类型卡住为ResponseEntity。换句话说,我想指定 StreamingOAuthService 方法支持的唯一类型是 ResponseEntity。如图所示,StreamingOAuthService.sendAndReceive 无法编译,因为返回类型是 Future[ResponseEntity] 而不是 Future[A],如指定的特质。

最佳答案

我对之前的答案进行了更多思考,即使在多类型形式中,它仍然不是很令人满意,因为您需要定义所有类型 A , B等您想要使用的基类的任何实例,然后该子类只能为每个方法接受这些类型。

类型运算符(广义类型约束)看起来提供了更好的选择:

trait Base {

  type T

  def fun1[A](input: String)(implicit tp: A <:< T): A

  def fun2[A](input: Int)(implicit tp: A <:< T): A
}

class RestrictedSub extends Base {

  override type T = Double

  def fun1[A](input: String)(implicit tp: A <:< T): A = {
    ...
  }

  def fun2[A](input: Int)(implicit tp: A <:< T): A = {
    ...
  }
}

对于任何方法的调用,编译器都可以提供合适的隐式 <:<[A,T] (通常写作 A <:< T ,类似于二元运算符)当且仅当 AT 的子类型,因此在编译时应禁止任何不适当的调用。

对于不受限制的子类(特征伴生对象中工厂方法的一个很好的候选者),类型 T可以设置为AnyAnyRef视情况而定。

不过,我确实注意到,我还没有尝试使用它来构建具有隐式 Unmarshaller 的特征的完整版本。和 Future返回类型,这可能会使正确的解决方案变得复杂。

关于Scala 类型 : How to Restrict the Generic Type of a Subclass?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32839272/

相关文章:

java - 使用泛型方法检查对象是否在数组中

java - 如何在 Java 中使用泛型和 Class<T> 类

javascript - 为什么 typeof 的结果与传入的表达式的计算结果不同?

scala - 如何在 Intellij Idea 11 上运行 scala 代码?

scala - 生成可能的组合

java - 泛型类中私有(private)迭代器出现奇怪的输入错误

types - 从列表中选择特定类型的项目

Haskell: `Num [a] => a`和 `Num a => [a]`有什么区别

scala - Scala 酸洗是否适用于 Scala 2.11?

scala - 在 flatMap 中使用 Try