Skip to content

Instantly share code, notes, and snippets.

@nicolas-zozol
Last active July 20, 2017 13:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nicolas-zozol/8c66352cbbad0ab67474a776cf007427 to your computer and use it in GitHub Desktop.
Save nicolas-zozol/8c66352cbbad0ab67474a776cf007427 to your computer and use it in GitHub Desktop.
Failing PECS conversion
package io.robusta.java.pecs;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by nicorama on 20/07/2017.
*/
public class ContravariantHeritage {
public static void main(String[] args) {
new ContravariantHeritage().launch();
}
void launch() {
// With super, you don't care what is already in the list
// as long as it will allow a Thing to be added;
List<? super Bamboo> pandaFood = new ArrayList<>();
pandaFood.add(new Bamboo());
List<Bamboo> food = new OhPanda().getMeals(); }
abstract class Restaurant {
Kitchen kitchen;
public Restaurant(Kitchen kitchen) {
this.kitchen = kitchen;
}
List<? extends Food> getMeals() {
List<Food> food = new ArrayList<>();
this.kitchen.build(food);
return food;
}
}
interface Kitchen {
void build(List<? super Food> dessert);
}
class PandaKitchen implements Kitchen{
@Override
public void build(List<? super Food> dessert) {
// PandaRestaurant is a Producer, but here we talk about List
// the List IS a consumer of bamboos
System.out.println("miam");
dessert.add(new Bamboo());
}
}
class MeatKitchen implements Kitchen{
@Override
public void build(List<? super Food> main) {
// PandaRestaurant is a Producer, but here we talk about List
// the List IS a consumer of bamboos
System.out.println("miam");
main.add(new Meat());
}
}
class OhPanda extends Restaurant {
public OhPanda() {
super(new PandaKitchen());
}
/**
* Huge difference between parameter and return
* a return from extended class can be more precise than Original
* But as a param, the contract MUST be the same
* Example: the equals() function
*/
@Override
List<Bamboo> getMeals() {
List<? super Food> bamboos = new ArrayList<>();
this.kitchen.build(bamboos);
return bamboos; /// <<<==== FAIL: would NOT compile
}
}
class Food {
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
class Meat extends Food {
}
class Bamboo extends Food {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment