37
ADSA: Subtypes/7 241-423 Advanced Data Structures and Algorithms Objective explain how subtyping/subclassing and generics are combined in Java introduce covariance and contravariance Semester 2, 2013-2014 7. Subtypes/subclas sing and Generics

ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

Embed Size (px)

Citation preview

Page 1: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 1

241-423 Advanced Data Structures and Algorithms

• Objective– explain how subtyping/subclassing and

generics are combined in Java– introduce covariance and contravariance

Semester 2, 2013-2014

7. Subtypes/subclassing and Generics

Page 2: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 2

Contents

1. The Substitution Principle

2. Subtyping of An Entire Collection

3. Subtyping/subclassing Terminology

4. Covariance: ? extends

5. Contravariance: ? super

6. The Get and Put Principle (PECS)

7. No Instance Creation with ?

Page 3: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 3

1. The Substitution Principle

• You can assign an object of any subclass to a class reference (variable).

Integer i = new Integer(6);

Number n = i; Number

Float Integer

extends

Number

reference

Integer

object

n

i

Page 4: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 4

Apple a = new Apple();

Fruit f = a;Fruit

Apple Strawberry

extends

Fruit

reference

Apple

object

f

a

Page 5: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 5

Subtyping of Collection Elements

• We can add an integer or a double to a collection of Numbers, because Integer and Double are subclasses of Number.

List<Number> nums = new ArrayList<Number>();

nums.add(2);

nums.add(3.14); // OK

Page 6: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 6

List<Number>

reference

Integer

object

nums . . .

Double

object

List<Number> object

Number

references

3.142

Page 7: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 7

2. Subtyping of An Entire Collection

• You might think that since Integer is a subclass of Number, then List<Integer> is a subclass of List<Number>. NO!!!

List<Integer> ints = Arrays.asList(2, 3);

List<Number> nums = ints; // compile-time err

Page 8: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 8

List<Number>

reference

Integer

object

nums . . .

Double

object

List<Integer> object

Integer

references

32

ints

Page 9: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 9

Why?

• It's to prevent run-time errors such as the following:

List<Integer> ints = new Integer[] {1,2};

List<Number> nums = ints;

// compile-time error

nums.add(3.12); // run-time error (not reached)

Page 10: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 10

Another Example

List<Apple> apples = ...;

List<Fruit> fruits = apples; // compile-time error

Page 11: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 11

• Just to confuse matters, Integer[] is a subclass of Number[].

Integer[] ints = new Integer[] {1,2,3};

Number[] nums = ints; // OK

nums[2] = 3.12; // run-time error (will be reached)

Arrays are Different

Page 12: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 12

3. Subtyping/subclassing Terminology

• Covariance: a class reference (variable) can point to a 'narrower' subclass object– e.g. Fruit f = new Apple();– narrower means "more specific"

• Contravariance: a class reference (variable) can point to a 'wider' superclass object– e.g from Integer to Number– not common in Java

• Invariant: not able to convert

Page 13: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 13

• Arrays are covariant:– Integer[] is also a Number[]

• Basic Generic classes are not covariant and not contravariant: they are invariant

• For example:– List<Integer> is not a subclass List<Number>– Also List<Number> is not a subclass of

List<Integer>

Page 14: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 14

Adding Covariance and Contravariance

• It is useful to allow covariance and contravariance in collections, so the Java designers added:– ? extends (extends wildcard) for covariance

– ? super (super wildcard) for contravariance

Page 15: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 15

4. Covariance: ? extends

List<Integer> ints = Arrays.asList(1,2);

List<? extends Number> nums = ints; // OK

•"? extends Number" means that it is OK to assign a subclass collection of Number to nums

– in this case, a collection of Integers

Page 16: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 16

• But we cannot put elements into the collection...

List<Integer> ints = Arrays.asList(1,2);

List<? extends Number> nums = ints; // OK

nums.add(3.12); // compile-time error

• This is the array situation, but with one big difference–the error is caught at compile-time

Page 17: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 17

Another ? Extends Example

List<Apple> apples = new ArrayList<Apple>();

List<? extends Fruit> fs = apples; // OK

fs.add(new Strawberry()); //compile-time err

•The code won't compile even if we try to add an Apple or a Fruit instance

fs.add(new Apple()); //compile-time err

fs.add(new Fruit()); //compile-time err

Page 18: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 18

• The restriction is because the compiler only knows that fs refers to a collection subclass of Fruit, but not which one.

Page 19: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 19

• The only thing we can add is null: fruits.add(null); // ok

• We can get data out of the structure but only as a Fruit instance (the ? extends class):Fruit get = fruits.get(0);

Page 20: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 20

Summary of ? extends

• It allows the assignment of a subclass collection to a superclass collection reference, but no element assignments are possible– quite restrictive

• Values can be removed, as instances of the superclass– useful Good for

'getting'

Good for

'getting'

Page 21: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 21

5. Contravariance: ? superList<Object> objs = Arrays.<Object>asList(1,"two");

List<? super Integer> vals = objs;

vats.add(3); // ok

•? super allows a superclass collection of Integer to be assigned to vals

– in this case, a list of Objects

•And you can add subclass elements to the collection later.

Page 22: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 22

Another ? super example

List<Fruit> fruits = new ArrayList<Fruit>();

List<? super Apple> apps = fruits;

apps.add(new Apple()); // OK

apps.add(new GreenApple()); // OK

apps.add(new Fruit()); // compile-time error

apps.add(new Object()); // compile-time error

•Only subclass elements of Apple can be added.

Page 23: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 23

Why?

• The compiler knows that apps refers to a superclass collection of Apple.

• It does not know which class, but all superclasses of Apple can store subclasses of Apple as new elements.

Page 24: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 24

Get Restriction with ? Super

• You can only get elements out of a ? super object as values of class Object:

Object ob1 = fruits.get(0);

Object ob2 = fruits.get(1);

Fruit f = (Fruit) fruits.get(0); // compile-time err

Page 25: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 25

Another Example

List<Object> objs = Arrays.<Object>asList(1,"two");

List<? super Integer> ints = objs;

String str = "";

for (Object obj : ints)

str += obj.toString(); // Object method

// str is "1two"

Page 26: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 26

Summary of ? super

• It allows the assignment of a superclass collection to a subclass reference, and further subclass additions are possible– useful

• Values can only be removed as Object instances– quite restrictive

Good for

'putting'

Good for

'putting'

Page 27: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 27

6. The Get and Put Principle (PECS)

– use ? extends when you only get values out of a collection; i.e. is a producer

– use ? super when you only put values into a collection; i.e. is a consumer

– don't use a wildcard when you both get and put

• PECS comes from "Producer Extends, Consumer Super"

Page 28: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 28

? extends Function example

public static double sum( Collection<? extends Number> nums)

{

double s = 0.0;

for (Number num : nums)

s += num.doubleValue();

return s;

}

PECS

producer(a Number method)

Page 29: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 29

• The following calls are legal:

List<Integer> ints = Arrays.asList(1, 2, 3);

double d = sum(ints); // == 6.0;

List<Double> doubles = Arrays.asList(2.78, 3.14);

double d = sum(doubles); // == 5.92;

List<Number> nums = Arrays.<Number>asList(1, 2, 2.78, 3.14);

double d = sum(nums); // == 8.92;

• The first two calls would not be legal if ? extends was not used.

Page 30: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 30

? super function example

public static void count( Collection<? super Integer> ints, int n)

{

for (int i = 0; i < n; i++)

ints.add(i);

}

PECS

consumer

Page 31: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 31

• The following calls are legal:

List<Integer> ints = new ArrayList<Integer>();

count(ints, 5);

// ints.toString().equals("[0, 1, 2, 3, 4]");

List<Number> nums = new ArrayList<Number>();

count(nums, 5);

nums.add(5.0);

// nums.toString().equals("[0, 1, 2, 3, 4, 5.0]");

List<Object> objs = new ArrayList<Object>();

count(objs, 5);

objs.add("five");

// objs.toString().equals("[0, 1, 2, 3, 4, five]");

• The last two calls need ? super in count()

Page 32: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 32

No wildcard example

public static double sumCount( Collection<Number> nums, int n)

{ count(nums, n);

return sum(nums);

}

•The nums collection is passed to both sum() and count(), so its element class must both extend Number (as sum() requires) and be super to Integer (as count() requires).

Number

Integer

? extend

? super

Page 33: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 33

• The only two classes that satisfy both of these constraints are Number and Integer, and I picked the first.

• A sample call:List<Number> nums = new ArrayList<Number>();

double sum = sumCount(nums,5);

Number

Integer

? extend

? super

Page 34: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 34

Using both ? extends and ? super

public static <T> void copy( List<? super Integer> dst, List<? extends Integer> src)

{ for (int i = 0; i < src.size(); i++)

dst.set(i, src.get(i));

}

•the destination list may already contains elements of any class that is a superclass of Integer

•the source list will have elements of any class that is a subclass of Integer.

PECS

Page 35: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 35

• A sample call:

List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");

List<Integer> ints = Arrays.asList(5, 6);

Collections.copy(objs, ints);

// objs is "[5, 6, four]"

Page 36: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 36

7. No Instance Creation with ?

• For example, the following are illegal:

List<?> list = new ArrayList<?>();

// compile-time error

Map<String, ? extends Number> map = new HashMap<String, ? extends Number>();

// compile-time error

Page 37: ADSA: Subtypes/7 1 241-423 Advanced Data Structures and Algorithms Objective –explain how subtyping/subclassing and generics are combined in Java –introduce

ADSA: Subtypes/7 37

• Usually we create a concrete collection first, even if we use wildcards later:

List<Number> nums = new ArrayList<Number>();

List<? super Number> sink = nums; // OK

for (int i=0; i<10; i++)

sink.add(i);