<commit_before><!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>What is contravariance?</title>
</head>
<body>
<p>
This article is a follow up to my <a href="http://www.translationdata.com/2016/01/what-is-covariance/" target="_blank">What is Covariance</a> article. If you read the previous article and understood the concept then contravariance should be relatively straight forward.</p>

<p>Here is sample program that demonstrates contravariance and covariance.</p>
<pre>
package com.translationdata;

import java.util.ArrayList;
import java.util.List;

public class Contravariance {
	public static void main(String[] args) {
		App app = new App();
		app.run();
	}
}

class App {
	public void run() {
		List<Animal> animals = new ArrayList<>();
		List<Mammal> mammals = new ArrayList<>();
		List<Human> humans = new ArrayList<>();

		animals.add(new Animal());
		animals.add(new Animal());
		animals.add(new Animal());
		
		mammals.add(new Mammal());
		mammals.add(new Mammal());
		mammals.add(new Mammal());
		
		humans.add(new Human());
		humans.add(new Human());
		humans.add(new Human());
		
		print("Before copy()", animals);
		
		Collections.copy(animals, humans);
		print("After copy()", animals);
		
		Collections.append(animals, mammals);
		print("After append()", animals);
		
		Animal animal = animals.get(4);
	}
	
		
	public void print(String context,List<? extends Animal> list) {
		for(int i = 0; i < list.size(); i++) {
			System.out.println(context + ": I am a " + list.get(i));
		}
		System.out.println();
	}
}
	
class Animal {
	String type = "animal";
	
	public String toString() {
		return type;
	};
}

class Mammal extends Animal {
	Mammal() {
		type = "mammal";
	}
}

class Human extends Mammal {
	Human() {
		type = "human";
	}
}

class Collections {
	public static <T> void copy(List<? super T> dest , List<? extends T> src ) {
		for(int i=0; i < src.size(); i++) {
			dest.set(i, src.get(i)); 
		}
		
		// src.add(new Animal());  // ERROR, insertion not allowed into a covariant type
	}
	
	public static <T> void append(List<? super T> dest , List<? extends T> src ) {
		for(int i=0; i < src.size(); i++) {
			dest.add(src.get(i)); 
		}
		
		//Animal animal = dest.get(4); // ERROR, reading a contravariant type is not allowed 
		Object animal = dest.get(4);   // except into an Object like this
	}
}

</pre>
<p>This is the program output:</p>
<pre>
Before copy(): I am a animal
Before copy(): I am a animal
Before copy(): I am a animal

After copy(): I am a human
After copy(): I am a human
After copy(): I am a human

After append(): I am a human
After append(): I am a human
After append(): I am a human
After append(): I am a mammal
After append(): I am a mammal
After append(): I am a mammal
</pre>
<p>Here is my informal definition of a contravariant datatype. A contravariant datatype is one that reverses the subtype relationship with another datatype. If type B is related to type A and B is a subtype of A then B is covariant with A, but if 
A is the subtype of B, then B is contravariant with A.</p>
<p>This is best understood by running the sample code and understanding how the <em>copy()</em> and <em>append()</em> functions work. The main point to remember about contravariance is that you cannot read the value contained in a contravariant type except if you place the value into an Object.</p>

<p>Why is that the case?</p>

<p>If you look at the generic type definition in the <em>append()</em> signature:</p>
<pre>public static <T> void append(List<? super T> dest , List<? extends T> src )</pre>
<p>and examine the <em>List&lt;? super T&gt; dest</em> type, you can see that the generic type is a supertype of T.</p> 

<p>Could you read the <strong>dest</strong> variable and place the result an Animal, Mammal, or Human variable?</p> 

<p>No, because the <em>apply()</em> function can receive any supertype of <strong>T</strong> including Object. If <em>List&lt;Object&gt;</em> is passed to <em>append()</em>, you cannot read one of the Objects from the list and place it in an Animal type because that violates the rules of polymorphism.</p>
<p>If you try reading the contravariant type you will get a nasty compiler error similar to:</p>
<pre>Type mismatch: cannot convert from capture#9-of ? super T to Animal</pre>
<br>
<p>An animal can do anything that an Object can do but not vice versa.</p>
<table border="1" width="80%">
<tr>
<td>
<pre>Object object = new Animal(); // is okay</pre>

<p>but</p>
<pre>Animal animal = new Object(); // generates a compiler error</pre>

</td>
</tr>
</table>

<br>
<p>You can however always read the dest variable into an Object variable. Since Object is the superclass of every class, this works. So the following will always work:</p>
<pre>Object object = new AnyClass(); // will always compile</pre>

<br>
<h3>Polymorphism Rules the Roost</h3>
<p>Why would you need contravariant types?</p>
<p> These types are useful when writing generic classes that have functions that work on generic types. The Java Collections class is an example. If you look at the <em>copy()</em> function, you will see contravariant and covariant types in the signature. This allows the function to work with many types not just the single type T.</p>
<p>That sums up my explanation of covariance and contravaiance.</p>
</body>
</html><commit_msg>Text edits<commit_after><!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>What is contravariance?</title>
</head>
<body>
<p>
This article is a follow up to my <a href="http://www.translationdata.com/2016/01/what-is-covariance/" target="_blank">What is Covariance</a> article. If you read the previous article and understood the concept then contravariance should be relatively straight forward.</p>

<p>Here is sample program that demonstrates contravariance and covariance.</p>
<pre>
package com.translationdata;

import java.util.ArrayList;
import java.util.List;

public class Contravariance {
	public static void main(String[] args) {
		App app = new App();
		app.run();
	}
}

class App {
	public void run() {
		List<Animal> animals = new ArrayList<>();
		List<Mammal> mammals = new ArrayList<>();
		List<Human> humans = new ArrayList<>();

		animals.add(new Animal());
		animals.add(new Animal());
		animals.add(new Animal());
		
		mammals.add(new Mammal());
		mammals.add(new Mammal());
		mammals.add(new Mammal());
		
		humans.add(new Human());
		humans.add(new Human());
		humans.add(new Human());
		
		print("Before copy()", animals);
		
		Collections.copy(animals, humans);
		print("After copy()", animals);
		
		Collections.append(animals, mammals);
		print("After append()", animals);
		
		Animal animal = animals.get(4);
	}
	
		
	public void print(String context,List<? extends Animal> list) {
		for(int i = 0; i < list.size(); i++) {
			System.out.println(context + ": I am a " + list.get(i));
		}
		System.out.println();
	}
}
	
class Animal {
	String type = "animal";
	
	public String toString() {
		return type;
	};
}

class Mammal extends Animal {
	Mammal() {
		type = "mammal";
	}
}

class Human extends Mammal {
	Human() {
		type = "human";
	}
}

class Collections {
	public static <T> void copy(List<? super T> dest , List<? extends T> src ) {
		for(int i=0; i < src.size(); i++) {
			dest.set(i, src.get(i)); 
		}
	}
	
	public static <T> void append(List<? super T> dest , List<? extends T> src ) {
		for(int i=0; i < src.size(); i++) {
			dest.add(src.get(i)); 
		}
	}
}

</pre>
<p>This is the program output:</p>
<pre>
Before copy(): I am a animal
Before copy(): I am a animal
Before copy(): I am a animal

After copy(): I am a human
After copy(): I am a human
After copy(): I am a human

After append(): I am a human
After append(): I am a human
After append(): I am a human
After append(): I am a mammal
After append(): I am a mammal
After append(): I am a mammal
</pre>
<p>Here is my informal definition of a contravariant datatype. A contravariant datatype is one that reverses the subtype relationship with another datatype. If type B is related to type A and B is a subtype of A then B is covariant with A, but if A is the subtype of B, then B is contravariant with A.</p>
<p>This is best understood by running the sample code and understanding how the <em>copy()</em> and <em>append()</em> functions work. The main point to remember about contravariance is that you cannot read the value contained in a contravariant type except if you place the value into an Object.</p>

<p>Why is that the case?</p>

<p>If you look at the generic type definition in the <em>append()</em> signature:</p>
<pre>public static <T> void append(List<? super T> dest , List<? extends T> src )</pre>
<p>and examine the <em>List&lt;? super T&gt; dest</em> type, you can see that the generic type is a supertype of T.</p> 

<p>Could you read the <em>dest</em> variable and place the result an Animal, Mammal, or Human variable?</p> 

<p>No, because the <em>apply()</em> function can receive any supertype of <strong>T</strong> including Object. If <em>List&lt;Object&gt;</em> is passed to <em>append()</em>, you cannot read one of the Objects from the list and place it in an Animal type because that violates the rules of polymorphism.</p>
<p>If you try reading the contravariant type you will get a nasty compiler error similar to:</p>
<pre>Type mismatch: cannot convert from capture#9-of ? super T to Animal</pre>
<br>
<p>An animal can do anything that an Object can do but not vice versa.</p>
<table border="1" width="80%">
<tr>
<td>
<pre>Object object = new Animal(); // is okay</pre>

<p>but</p>
<pre>Animal animal = new Object(); // generates a compiler error</pre>

</td>
</tr>
</table>

<br>
<p>You can however always read the <em>dest</em> variable into an Object variable. Since Object is the superclass of every class, this works. So the following will always work:</p>
<pre>Object object = new AnyClass(); // will always compile</pre>

<br>
<p>Why Would You Need Contravariant Types?</p>
<p> These types are useful when writing generic classes that have functions that work on generic types. The Java Collections class is an example. If you look at the <em>copy()</em> function, you will see contravariant and covariant types in the signature. This allows the function to work with many types not just the single type T.</p>
</body>
</html>
{'fraction_non_alphanumeric': 0.13242718446601942, 'fraction_numerical': 0.004077669902912621, 'mean_word_length': 4.091942659416707, 'pattern_counts': {'":': 2, '<': 221, '<?xml version=': 0, '>': 215, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4024962', 'n_tokens_mistral': 3445, 'n_tokens_neox': 3164, 'n_words': 1373}