Contravariance vs Covariance in Scala

后端 未结 3 647
無奈伤痛
無奈伤痛 2020-12-05 05:40

I just learned Scala. Now I am confused about Contravariance and Covariance.

From this page, I learned something below:

Covariance

Perhaps the most o

3条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-05 06:33

    A Good recent article (August 2016) on that topic is "Cheat Codes for Contravariance and Covariance" by Matt Handler.

    It starts from the general concept as presented in "Covariance and Contravariance of Hosts and Visitors" and diagram from Andre Tyukin and anoopelias's answer.

    And its concludes with:

    Here is how to determine if your type ParametricType[T] can/cannot be covariant/contravariant:

    • A type can be covariant when it does not call methods on the type that it is generic over.
      If the type needs to call methods on generic objects that are passed into it, it cannot be covariant.

    Archetypal examples:

    Seq[+A], Option[+A], Future[+T]
    
    • A type can be contravariant when it does call methods on the type that it is generic over.
      If the type needs to return values of the type it is generic over, it cannot be contravariant.

    Archetypal examples:

    `Function1[-T1, +R]`, `CanBuildFrom[-From, -Elem, +To]`, `OutputChannel[-Msg]`
    

    Regarding contravariance,

    Functions are the best example of contravariance
    (note that they’re only contravariant on their arguments, and they’re actually covariant on their result).
    For example:

    class Dachshund(
      name: String,
      likesFrisbees: Boolean,
      val weinerness: Double
    ) extends Dog(name, likesFrisbees)
    
    def soundCuteness(animal: Animal): Double =
      -4.0/animal.sound.length
    
    def weinerosity(dachshund: Dachshund): Double =
      dachshund.weinerness * 100.0
    
    def isDogCuteEnough(dog: Dog, f: Dog => Double): Boolean =
      f(dog) >= 0.5
    

    Should we be able to pass weinerosity as an argument to isDogCuteEnough? The answer is no, because the function isDogCuteEnough only guarantees that it can pass, at most specific, a Dog to the function f.
    When the function f expects something more specific than what isDogCuteEnough can provide, it could attempt to call a method that some Dogs don’t have (like .weinerness on a Greyhound, which is insane).

提交回复
热议问题