Questions tagged [contravariance]

Within the type system of a programming language, covariance and contravariance refers to the ordering of types from narrower to wider and their interchangeability or equivalence in certain situations (such as parameters, generics, and return types)

Within the type system of a programming language, a typing rule or a type conversion operator is:

covariant if it preserves the ordering, ≤, of types, which orders types from more specific to more generic;

contravariant if it reverses this ordering, which orders types from more generic to more specific;

invariant if neither of these applies.

These terms come from category theory, which has a general definition of covariance and contravariance that unifies the computer science definition of these terms with the definition used in vector spaces.

This distinction is important in considering argument and return types of methods in class hierarchies. In object-oriented languages such as Python, if class B is a subtype of class A, then all member functions of B must return the same or narrower set of types as A; the return type is said to be covariant. On the other hand, if the member functions of B take the same or broader set of arguments compared with the member functions of A, the argument type is said to be contravariant. The problem for instances of B is how to be perfectly substitutable for instances of A. The only way to guarantee type safety and substitutability is to be equally or more liberal than A on inputs, and to be equally or more strict than A on outputs. Note that not all programming languages guarantee both properties in every context, and that some are unnecessarily strict; they are said not to support covariance or contravariance in a given context; the behavior of some programming languages is discussed below.

Typical examples:

The operator which constructs array types from element types is usually covariant on the base type: since String ≤ Object then ArrayOf(String) ≤ ArrayOf(Object). Note that this is only correct (i.e. type safe) if the array is immutable; if insert and remove operators are permitted, then the insert operator is covariant (e.g. one can insert a String into an ArrayOf(Object)) and the remove operator is contravariant (e.g. one can remove an Object from an ArrayOf(String)). Since the mutators have conflicting variance, mutable arrays should be invariant on the base type.

Let f be a function with a parameter of type T and let g be a function with a parameter of type S, both with the same return type. If T ≤ S, then g ≤ f. g can replace f anywhere, since it cares less about the type of its parameter, and both return the same type. Because the subtype relation between the argument type and the functions is reversed, the function type is said to be contravariant on its argument type.

Let f be a function that returns a value of type T and let g be a function that returns a value of type S, both with the same parameter type. If T ≤ S, then f ≤ g. f can replace g anywhere, since it returns only a subset of all possible values returned by g, and both take the same argument. Because the subtype relation between the argument type and the functions is preserved, the function type is said to be covariant on its return type.

In object-oriented programming, substitution is also implicitly invoked by overriding methods in subclasses: the new method can be used where the old method was invoked in the original code. Programming languages vary widely on their allowed forms of overriding, and on the variance of overridden methods' types.

540 questions
0
votes
1 answer

Questioning about Contra-variance in TDD

I am currently learning TDD and i was wondering about the real meaning of Uncle Bob's sentence about refacto step in connection with TDD. The subject talks about Test Contra-variance in TDD and it comes from his Clean Coder Blog. Context : Suppose I…
MigMax
  • 80
  • 4
0
votes
1 answer

Passing an interface to another interface method

I need to implement an event-listener model in OOP. Now I have EventInterface and ListenerInterface. But I want to pass the event to a listener, as: interface ListenerInterface { public function listen(EventInterface $event); } But I can't do…
Alexxosipov
  • 1,215
  • 4
  • 19
  • 45
0
votes
0 answers

C# contravariance with method arguments

I'm trying to solve some simple study task, which includes writing an interpreter of some simple language with 4 methods - Set, Sum, Print, Remove; first 2 methods have 2 arguments - variable name and int value to set to variable or sum to its…
0
votes
1 answer

Right use of covariant and contravariance in kotlin for treeview

Hello stackoverflow communtiy, I wrote a method using generic types. And I have the strange feeling that it's a little bit to complex. On the internet I found the concept of contra variance and variance for generic types. But my attempts to do it…
Christian
  • 739
  • 1
  • 5
  • 15
0
votes
0 answers

Kotlin: storing and invoking functions with type parameter in generic collections

I am writing simple expert system in Kotlin. Let's start with the facts. I implemented Fact as follows: data class Fact(val id: String, val value: T) To give an example, it's instance would look like this: val f1 = Fact("adult", true)…
PGliw
  • 311
  • 4
  • 9
0
votes
3 answers

Contravariance/Covariance - cannot convert class to interface

I have the following code public interface IInterface { } public class GenericClass where TSomeClass : class { public TSomeClass SomeMethod(TSomeClass someClass = null) { return SomeClass.SomeClassStaticInstance; …
0
votes
2 answers

Why passing Int => Int to a function taking AnyVal => Int results in type mismatch when Int extends AnyVal?

I'm new to scala and I'm having some hard time with passing a func as a parameter to a different func. The function that I'm trying to pass should get an argument but I dont know its type (but its a value defenitly): object Sing def…
JeyJ
  • 3,582
  • 4
  • 35
  • 83
0
votes
1 answer

What's the difference between contravariance and inheritance in Java?

I have a parent class A, and its child class B. What is the difference between these two snippets : public static void main (String[] args) { ArrayList e = new ArrayList<>(); B thing = new B(); e.add(thing); …
Zee
  • 824
  • 11
  • 25
0
votes
1 answer

How Pass Generics class as parameter with constraint type methods available

I am still trying to fully understand generics especially when used in conjunction with base classes. I have a generic table class that takes in a derived type of a row class but is constrained to be a base row. Since the base table class is…
user3284717
  • 35
  • 1
  • 6
0
votes
0 answers

Question on covariance and contravariance

I have read in so many blogs that a method's inputs are contravariant and return type is covariant. As for as I understand, both are covariant (where in place of actual type, it's subtype can be given). This can be demonstrated with the below…
user3103957
  • 636
  • 4
  • 16
0
votes
1 answer

Scala type variance

I have the following code class Person class Warrior extends Person trait Commander[A] { def giveOrder(to: A) def delegate(to: Commander[A]) } val warCommander: Commander[Warrior] = new Commander[Warrior] { override def giveOrder(to:…
gurghet
  • 7,591
  • 4
  • 36
  • 63
0
votes
1 answer

Why does Scala function allow subclass parameter when specifyied super class parameter

<: seems to work like I'd expect, however, >: does not. object TheCakeIsALie extends App { class Food class Junk extends Food class Cake extends Junk val food = new Food val junk = new Junk val cake = new Cake def subJunk[T <:…
dwarfer88
  • 115
  • 1
  • 6