Covariance And Contravariance - A Simple Guide
Written by Mike James   
Friday, 20 November 2020
Article Index
Covariance And Contravariance - A Simple Guide
Object Hierarchies
Why Bother?

What's the point?

Now you understand the idea of covariance and contravariance you might be wondering what the point is?

The answer is that it is all a matter of when a language, or a language implementation, should, or could, allow automatic type conversion.

As array construction is covariant, if T(B) constructs an array of type B, it is fairly safe to treat an array of B as being an array of A without needing an explicit type conversion.

In many languages you can indeed write:

string[] x=new string[];
object[] y=a;

without the need for a cast and this is because object>string implies object[]>string[]. 

For a more involved example consider the C# delegate.

A delegate is a type that can wrap a function with a specific signature. A delegate accepts a function as input parameter and returns a delegate type that wraps it.

Consider a delegate

delegate Mydelegate(functionB);

and two functions which only differ in the type of their input parameter then A>B implies by contravariance:

functionA(A param)<functionB(B param);

Hence functionA can be used anywhere functionB can and so it should be safe to use Mydelegate to wrap an instance of a function that has parameters that are less derived than it.

By a similar argument a delegate:

delegate Mydelegate(A function);

which wraps a function which returns an A should be quite safe wrapping a function that returns a B as A>B implies by covariance that A function>B function and so you can use a B function anywhere you can use an A function. Thus delegates are covariance in the return parameter of the function they wrap and so can safely wrap a function that returns a more derived result.

Is it worth it?

Is it worth introducing what appear to be complex ideas like covariance and contravariance?

In practical work probably not as the whole thing is usually simple enough to work out from first principles.

For example, can an array of strings be used in place of an array of objects?

Well yes obviously as a string is just an object with additional properties and methods so it can always be treated as an object.

So if you want to just think about type conversion and substitution rules from first principles that's fine. If you want to dress the idea up in the terms covariance and contravariance that's fine too.

However, the academic terms do have the disadvantage that it's easy to miss practical concerns.

Languages have to be pragmatic and this means they don't always obey the substitution principle.

For example a double can always be used where an integer can be used - e.g. write 1.0  in place of 1 but in practice it it rare for a language to define a double as a derived type of int.

For another example, consider the array of string types. If this is cast to an array of object types then this works for all read access but write access often fails. For example, try

string[] mystring=new string[10];
object[] myobject=mystring;
object[5]=123;

in most languages this will fail because the underlying type of the object element is string and not object but by the substitution principle it should work. In this case it is a result of inheritance not being implemented fully, i.e. an array of strings isn't really an array of objects with some additional properties.

In practice programming is more complicated and messy that pure theory allows.

Look out for a follow-on article that explains covariance and contravariance in C# in more detail.

arrowscontraandco

Related Articles

Strong typing

Casting – the escape from strong typing

Introduction to Delegates

Barbara Liskov Admitted to National Inventors Hall of Fame       

   

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

 

Banner


Google Intensive AI Course - Free On Kaggle
05/11/2024

Google is offering a 5-Day Gen AI Intensive Course designed to equip data scientists with the knowledge and skills to tackle generative AI projects with confidence. It runs on the Kaggle platform from [ ... ]



IBM Updates Granite Models
28/10/2024

IBM has released new Granite models that it says provide state-of-the-art performance relative to model size. The Granite 3.0 collection includes a new, instruction-tuned, dense decoder-only LLM.


More News

espbook

 

Comments




or email your comment to: comments@i-programmer.info

 

<ASIN:1871962439>

<ASIN:1871962587>

 



Last Updated ( Friday, 20 November 2020 )