为什么T处于协方差位置或逆变位置

时间:2017-08-02 22:51:12

标签: scala

  1. 给出以下类定义

    class X [+ T] {   def get [U>:T] (default:U):U }

  2. 为什么方法def get[U>:T]中的T(默认值:U)处于协方差位置

    1. 给出以下类定义

      class X [-T] {   def get [U<:T] (default:U):U }

    2. 为什么方法def get[U<:T]中的T(默认值:U)处于协方差位置

1 个答案:

答案 0 :(得分:1)

很难回答&#34;为什么?&#34;问题没有你提供更多细节,但我会尝试。我认为你的问题确实是&#34;为什么U上的类型限制没有被反转?&#34;。简短的回答:因为这是类型安全的,并且涵盖了一些其他方面没有涉及的情况。

您的第一个示例可能受Option[T]及其getOrElse方法的启发。虽然我不确定为什么任何人需要getOrElse UT不同,但逻辑为什么类型限制只能U>:T对我来说是显而易见的。我们假设您有3个类:C继承B,继承A并且您有Option[B]。如果您的default值已经BC,那么除了U = T之外,您不需要任何其他内容,因此签名更简单,无需额外的通用{{} 1}}就足够了。如果您的某种类型不是U的子类型(例如getOrElse),那么您无法将默认值传递给B方法的唯一情况就是如此。让我们暂时延长这个签名

A

类型def getOrElse[U, R](default:U): R UT应该如何相关?显然,R应该是RU的常见超类型,因为它应该能够同时包含TT。然而,这样的定义将是一种矫枉过正。首先,拥有一个与U无关的类型的默认值真的很奇怪。其次,即使是如此奇怪的情况,您(和编译器)仍然可以计算一个常见的超类型并将其分配给一些新的T = U'。因此,您不需要R',但添加R会增加一些灵活性(至少在理论上)。但是U仍然必须是U的超类型,因为它也是返回类型。

总而言之:添加TU

    如果您使用U<:T作为结果类型,则
  • 会生成错误的代码(U因为结果类型无法保留U
  • 或者如果您使用T作为结果类型将不会扩展此方法的适用性,即不允许任何不使用T编译的代码使用此附加U进行编译。

但是将U添加到U将允许更多代码实际上是类型安全的编译,例如(是的,愚蠢的例子,但正如我所说,我不知道任何现实生活实施例):

U>:T