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

Can't contravariance be implemented with interfaces?

I'm at the point where I'm starting to grasp contravariance, although I'm trying to work out what the advantage is when an interface can be used instead. Obviously I'm missing something. Here is the c#4 example class Dog : Animal { public…
Razor
  • 17,271
  • 25
  • 91
  • 138
0
votes
2 answers

C# generics is keyword covariance / contravariance type inferral

Please consider this interface: public interface IInitialiazableEntity where TRepository : class, IRepository { void Initialize(TRepository repository); } This class (snippet): public class SomeFacade where TRepository…
h.alex
  • 902
  • 1
  • 8
  • 31
0
votes
1 answer

Covariance with Function return Types

I have roughly the following Type Hierarchy, (I know that all edges on a NonPolygon will not be arcs. I am attempting to do Extrusions on all PlaneRegions resulting in returned Solid objects. When I extrude a Polygon I want to return a Polyhedron.…
jth41
  • 3,808
  • 9
  • 59
  • 109
0
votes
3 answers

method variance: Return a list of abstract supertype after inserting concrete elements

I am writing insertInOrder function for a superclass, but cannot access the value age from the method: abstract class Parent(age: Int) case class Child1(age: Int) extends Parent(age) case class Child2(age: Int) extends Parent(age) def insertInOrder…
Asad Iqbal
  • 3,241
  • 4
  • 32
  • 52
0
votes
1 answer

Scala: arguments contravariant and return types are covariant why?

In the FP in Scala course, Martin mentions, the arguments are "contravariant" while the return types are "covariant". I don't think I understood that completely - can someone help with this one?
Somasundaram Sekar
  • 5,244
  • 6
  • 43
  • 85
0
votes
1 answer

Does normal object base type - derived type conversion come under Covariance and contravariance?

Covariance and contravariance provides implicit reference conversion for Arrays, Delegates and Generic parameter types. IEnumerable strings = new List(); IEnumerable objects = strings; Action actObject =…
Anoob K A
  • 59
  • 8
0
votes
0 answers

Reason for certain restrictions on variance conversions in C#

I have a few questions about the way implicit conversions between method delegates with regards to covariance and contravariance are implemented in C#. delegate void ImplicitFunction(T thing); delegate void ExplicitFunction(T…
0
votes
2 answers

Child to parent generic convertion in c#

I have my base interface class: public interface IAlgorithm where T : IParams { /// /// Contains algorythm parameters /// T Params{ get; set; } } And public interface IParams { } Then I…
makambi
  • 1,100
  • 3
  • 13
  • 30
0
votes
2 answers

How is Scala's Covariance, Contravariance useful?

I've been learning about scala's use of covariance and contravariance parameterized typing; I'm a bit perplexed by the following example code: class Thing class Creature extends Thing class Human extends Creature class Dog extends Creature class…
blogscot
  • 41
  • 7
0
votes
2 answers

Manipulate generic objects in parent abstract class (covariance/contravariance)

I'm trying to implement a system that allows to read and interpret lines from a file. I need to manage different file formats. For that I have an abstract Importer class that is is inherited and implemented differently (based on the file…
Olivier Payen
  • 15,198
  • 7
  • 41
  • 70
0
votes
1 answer

Create open instance delegate via reflection

Why does the following Delegate.CreateDelegate produce a runtime ArgumentException? static class Module1 { public static void Main() { MyDataObject mdo = new MyDataObject(); mdo.DoMagic("Hello"); } #region Assembly…
Alex B.
  • 2,145
  • 1
  • 16
  • 24
0
votes
2 answers

How do I store a collection of ObservableCollection with different types for T?

I have a class ActiveList: ObservableCollection that I wish to store in a dictionary with key of Type, which is the T of ActiveList, something like: Dictionary> Of course the dictionary cannot be typed, as it should cater…
ProfK
  • 49,207
  • 121
  • 399
  • 775
0
votes
1 answer

Which overloaded methods are added to the delegate?

The following is a question I've seen on a test which raised some questions: Given the following code: public delegate B func(B b); public class A { public func x; public int i = 2; public A(int i) { this.i = i; x += f; } public…
matanc1
  • 6,525
  • 6
  • 37
  • 57
0
votes
1 answer

Correct way to declare a method with two type parameters in inheritance hierarchy

When writing a method that takes two objects, with two type parameters in a subtype-supertype relation, what is the best way of declaring your intentions out of these options? Declare both super and extends: public static void copy(List
thecoop
  • 45,220
  • 19
  • 132
  • 189
0
votes
2 answers

C# - Generic method calling method which returns concrete type?

Say you have a method that takes a Generic type, and e.g. an enum eType as well as a concrete object. The Method then determines which method to call based on the enum Type. Each private method being called knows its own return type (instantiates a…
lko
  • 8,161
  • 9
  • 45
  • 62
1 2 3
35
36