Scala';s协方差、逆变换有用吗?

Scala';s协方差、逆变换有用吗?,scala,covariance,contravariance,Scala,Covariance,Contravariance,我一直在学习scala使用协方差和反方差参数化类型;下面的示例代码让我有点困惑: class Thing class Creature extends Thing class Human extends Creature class Dog extends Creature class Home[T >: Creature] { private var inside = Set[T]() def enter(entering: T) = inside += entering

我一直在学习scala使用协方差和反方差参数化类型;下面的示例代码让我有点困惑:

class Thing
class Creature extends Thing
class Human extends Creature
class Dog extends Creature

class Home[T >: Creature] {
  private var inside = Set[T]()

  def enter(entering: T) = inside += entering

  def whoIsInside = inside
}

val house = new Home[Thing]
val cage = new Home[Creature]
house enter new Human
cage enter new Dog
据我所知,参数化类Home使用了生物下限的逆变,所以

val flat = new Home[Human]

导致编译器错误,这是我所期望的。我的困境是,我创造了一个新的“房子”,但我可以把一个“人”放进去!虽然这也是有道理的,因为“人”是一个“东西”,我天真地期待它会失败!抛开力学不谈,协方差和逆变如何有用?

在您的示例中,您可以将T的子类型放入T的集合中,因为U在回答问题之前,我需要注意两件事:

a) 在您的示例中,您没有使用协方差/逆方差,您只是定义了一个下限

b) 在标题中,您暗示这是一个Scala概念。协方差和逆方差是面向对象的一般概念,早在Scala之前就存在了

那么关于你最初的问题,它有什么用处呢?它允许您为参数化类型指定继承。例如,如果将类型参数定义为协变,可能将生物作为上限,则可以表示狗的家可以代替生物的家:

scala> class Home[+T <: Creature]
defined class Home

scala> var home = new Home[Creature]
home: Home[Creature] = Home@46a32efb

scala> home = new Home[Dog]
home: Home[Creature] = Home@1b955e70
scala>class Home[+T var Home=新家[生物]
家:家[生物]=Home@46a32efb
scala>家=新家[狗]
家:家[生物]=Home@1b955e70
所以家[狗]是家[生物]的一个子类型-协方差允许你表达这一点


另外请注意,在您的示例中,如果您允许输入,则仅使类型参数协变不会编译。方法参数不能协变,因为这会破坏可替换性。Scala编译器将为您检测到这一点。

您的示例与协变无关,请参阅以获得深入的解释。我注意,如果包括Home的原始主体编译器在Home[+T]和Home[-T]中停止运行。
class Home[-T]
val cage: Home[Human] = new Home[Creature]
scala> class Home[+T <: Creature]
defined class Home

scala> var home = new Home[Creature]
home: Home[Creature] = Home@46a32efb

scala> home = new Home[Dog]
home: Home[Creature] = Home@1b955e70