Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do covariance/contravariance imply read-only/write-only?

If you take a look at the flow docs on covariant/contravariant fields in interfaces, covariant implies read-only and contravariance implies write-only. However, I don't really understand why. In their docs on variance, they're defined as

Covariance

  • Covariance does not accept supertypes.
  • Covariance does accept subtypes.

Contravariance

  • Contravariance does accept supertypes.
  • Contravariance does not accept subtypes.

But that doesn't really map to read-only/write-only in my mind. Could anyone explain more in depth why it's the case?

like image 657
m0meni Avatar asked Sep 18 '18 00:09

m0meni


People also ask

What does covariance and Contravariance mean?

Covariance and contravariance are terms that refer to the ability to use a more derived type (more specific) or a less derived type (less specific) than originally specified. Generic type parameters support covariance and contravariance to provide greater flexibility in assigning and using generic types.

Why is covariance and Contravariance important?

This enables you to assign to delegates not only methods that have matching signatures, but also methods that return more derived types (covariance) or that accept parameters that have less derived types (contravariance) than that specified by the delegate type.

What is the difference between covariance and Contravariance in delegates?

Covariance permits a method to have return type that is more derived than that defined in the delegate. Contravariance permits a method that has parameter types that are less derived than those in the delegate type.

What is covariance and Contravariance in generics in Java?

Covariance can be translated as "different in the same direction," or with-different, whereas contravariance means "different in the opposite direction," or against-different. Covariant and contravariant types are not the same, but there is a correlation between them. The names imply the direction of the correlation.


1 Answers

I'm not familiar with the syntax of the language, so this answer is in pseudo-code.

Imagine we have three types, Siamese < Cat < Animal, and define an interface

interface CatCage {
    cat: Cat
}

and write some methods

get_cat_in_cage (CatCage c) -> Cat {
    c.cat
}

put_cat_in_cage (Cat c, CatCage cage) {
    cage.cat = c
}

Covariance

If we make the field covariant, we can define an instance like

SiameseCage < CatCage {
    cat : Siamese
}

But if we do

put_cat_in_cage (aCat, aSiameseCage)

What is the value of aSiameseCage.cat in this instance? SiameseCage thinks it ought to be a Siamese, but we've just been able to make it a Cat - clearly, the field can't be writeable on the interface and be covariant at the same time.

Contravariance

If we make the field contravariant, we can define an instance like

AnimalCage < CatCage {
    cat : Animal
}

But now we can't do

get_cat_in_cage (anAnimalCage)

As the value of anAnimalCage.cat isn't guaranteed to be a Cat. So the field can't be readable on the interface if it's contravariant.

You could potentially make it readable on the interface by returning an Object, or whatever the base type is, but that probably wouldn't have any real use case, so the language is sensible in deciding against it.

like image 84
Isaac van Bakel Avatar answered Oct 27 '22 01:10

Isaac van Bakel