Basicjava04 Polymorphism Slides
Basicjava04 Polymorphism Slides
Kozsik Tamás
Polymorphism overview
Motivating example
An earlier example
public class Receptionist {
public Time[] readWakeupTimes(String[] fnames) {
Time[] times = new Time[fnames.length];
Motivating example
Motivating example
Generics: ArrayList
Alternative: java.util.ArrayList
convenient standard library, similar inner workings
names[0] = "Tom";
String mouse = names[1];
Generics: ArrayList
Alternative: java.util.ArrayList
convenient standard library, similar inner workings
Generics: ArrayList
Example updated
public class Receptionist {
...
public ArrayList<Time> readWakeupTimes(String[] fnames) {
ArrayList<Time> times = new ArrayList<Time>();
for (int i = 0; i < fnames.length; ++i) {
try {
times.add(readTime(fnames[i]));
} catch (java.io.IOException e) {
System.err.println("Could not read " + fnames[i]);
}
}
return times; // possibly sort before returning
}
}
Generics: ArrayList
Parametrized type
ArrayList<Time> times
Time[] times
Time times[]
Generics: ArrayList
Generic class
Generics: ArrayList
import java.util.ArrayList;
...
ArrayList<Time> times;
ArrayList<String> names = new ArrayList<String>();
ArrayList<String> namez = new ArrayList<>();
Generics: ArrayList
Generic method
import java.util.*;
public class Main {
public static <T> void reverse(T[] array) {
int lo = 0, hi = array.length-1;
while (lo < hi) {
T tmp = array[hi];
array[hi] = array[lo];
array[lo] = tmp;
++lo; --hi;
}
}
public static void main(String[] args) {
reverse(args);
System.out.println(Arrays.toString(args));
}
}
Kozsik Tamás Programming languages Java 11 / 108
Generics Inheritance Interface Subtyping Cast
Generics: ArrayList
Generics: ArrayList
Parametric polymorphism
▶ methods
Generics: ArrayList
Type parameter
Primitive types not allowed!
ArrayList<int> numbers // compilation error
Generics: ArrayList
Type parameter
Primitive types not allowed!
ArrayList<int> numbers // compilation error
Generics: ArrayList
Type parameter
Primitive types not allowed!
ArrayList<int> numbers // compilation error
Generics: ArrayList
Generics: ArrayList
Set
HashSet<String> colors = new HashSet<>();
colors.add("red"); colors.add("white"); colors.add("red");
int two = colors.size();
Generics: ArrayList
Set
HashSet<String> colors = new HashSet<>();
colors.add("red"); colors.add("white"); colors.add("red");
int two = colors.size();
Mapping
HashMap<String,String> colors = new HashMap<>();
colors.put("red", "piros"); colors.put("white", "fehér");
String whiteHu = colors.get("white");
Implementation of generics
Generic class
Implementation of generics
Implementation of generics
Type erasure
Type erasure
Type erasure
Type erasure
Type erasure
import java.util.ArrayList;
...
ArrayList<String> parametrized = new ArrayList<>();
parametrized.add("Romeo");
parametrized.add(12); // compilation error
String s = parametrized.get(0);
Type erasure
import java.util.ArrayList;
...
ArrayList<String> parametrized = new ArrayList<>();
parametrized.add("Romeo");
parametrized.add(12); // compilation error
String s = parametrized.get(0);
ArrayList raw = new ArrayList();
raw.add("Romeo");
raw.add(12);
Object o = raw.get(0);
Type erasure
Type erasure
Type erasure
Type erasure
Type erasure
Warning-free
Inheritance
Inheritance
Inheritance
Inheritance
Inheritance
Inheritance
Inheritance
Inheritance
Inheritance
Example
public class Time {
private int hour, min; // initialized to 00:00
public int getHour() { ... }
public int getMin() { ... }
public void setHour(int hour) { ... }
public void setMin(int min) { ... }
public void aMinPassed() { ... }
}
Inheritance
Example
public class Time {
private int hour, min; // initialized to 00:00
public int getHour() { ... }
public int getMin() { ... }
public void setHour(int hour) { ... }
public void setMin(int min) { ... }
public void aMinPassed() { ... }
}
Inheritance
Inheritance
java.lang.Object
Constructors
Constructors
Constructors
Constructors
Constructors
Constructors
Constructors
Constructors
Constructors
Constructors
class A {}
Constructors
class A {}
Constructors
Constructors in a class
Constructors
Constructor body
1st statement
• Explicit this call
• Explicit super call
• Implicit (automatically generated) super() call (no-arg!)
Constructors
Interesting error
Overriding
Overriding
package java.lang;
public class Object {
...
public String toString() {...} //java.lang.Object@4f324b5c
}
Overriding
package java.lang;
public class Object {
...
public String toString() {...} //java.lang.Object@4f324b5c
}
Overriding
Slightly better
redefinition, overriding
package java.lang;
public class Object {
...
public String toString() {...} //java.lang.Object@4f324b5c
}
Overriding
Slightly better
redefinition, overriding
package java.lang;
public class Object {
...
public String toString() {...} //java.lang.Object@4f324b5c
}
Overriding
package java.lang;
public class Object {
...
public String toString() {...} //java.lang.Object@4f324b5c
}
Overriding
package java.lang;
public class Object {
...
public String toString() {...} //java.lang.Object@4f324b5c
}
Overriding
Calling super.toString()
package java.lang; // java.lang.Object@4f324b5c
public class Object {... public String toString() {...} ... }
Overriding
Calling super.toString()
package java.lang; // java.lang.Object@4f324b5c
public class Object {... public String toString() {...} ... }
Overriding
Calling super.toString()
package java.lang; // java.lang.Object@4f324b5c
public class Object {... public String toString() {...} ... }
Overriding
package java.lang;
public final class Integer extends Number {
...
public static int parseInt(String str) { ... }
...
public @Override String toString() { ... }
public static String toString(int i) { ... }
public static String toString(int i, int radix) { ... }
...
}
Overriding
Differences
Overloading
• Methods/ctors with same name but different parameters
• Introduced method may overload inherited one (Java-specific)
• Compiler selects method/ctor based on actual parameters
Overriding
• Override a method defined in a base class
• Same name, same parameters
⋄ Same method
⋄ A method may have multiple implementations
• The most specific implementation is chosen run-time
Overriding
System.out
public void println( int value) { ... }
public void println(Object value) { ... } //value.toString()
...
System.out.println(7); // 7
System.out.println("Samurai"); // Samurai
System.out.println(new Time(21,30)); // 21:30
protected
protected
protected visibility
package java.util;
public abstract class AbstractList<E> implements List<E> {
...
protected int modCount;
protected AbstractList() { ... }
protected void removeRange(int fromIndex, int toIndex) { ...
...
}
• In the same package
• In subclasses (potentially in different packages)
private ⊆ package-private ⊆ protected ⊆ public
protected
class Counter {
private int counter = 0;
public int count() { return ++counter; }
}
protected
“Fixed”
class Counter {
private int counter = 0;
public int count() { return ++counter; }
}
protected
protected
package my.basic.types;
public class Counter {
protected int counter = 0;
public int count() { return ++counter; }
}
package my.advanced.types;
class SophisticatedCounter extends my.basic.types.Counter {
public int count(int increment) {
return counter += increment;
}
}
Interface
Interface
Interface
An interface definition
Interface
Interface
Interface
Generic interface
java/util/List.java
package java.util;
public interface List<T> {
T get(int index);
void set(int index, T item);
void add(T item);
...
}
java/util/ArrayList.java
package java.util;
public class ArrayList<T> implements List<T> {
public ArrayList() { ... }
@Override public T get(int index) { ... }
...
}
Kozsik Tamás Programming languages Java 57 / 108
Generics Inheritance Interface Subtyping Cast
Interface
Linked representation
package java.util;
Implementation of an interface
Implementation of an interface
Rational.java
public interface Rational {
int getNumerator();
int getDenominator();
Rational times(Rational that);
}
Fraction.java
public class Fraction implements Rational {
private final int numerator, denominator;
public Fraction(int numerator, int denominator) { ... }
public int getNumerator() { return numerator; }
public int getDenominator() { return denominator; }
public Rational times(Rational that) { ... }
}
Kozsik Tamás Programming languages Java 59 / 108
Generics Inheritance Interface Subtyping Cast
Implementation of an interface
Multiple implementations
Fraction.java
public class Fraction implements Rational {
private final int numerator, denominator;
public Fraction(int numerator, int denominator) { ... }
public int getNumerator() { return numerator; }
public int getDenominator() { return denominator; }
public Rational times(Rational that) { ... }
}
Simplified.java
public class Simplified implements Rational {
...
public int getNumerator() { ... }
public int getDenominator() { ... }
Rational times(Rational that) { ... }
}
Kozsik Tamás Programming languages Java 60 / 108
Generics Inheritance Interface Subtyping Cast
Implementation of an interface
Subtyping
Implementation of an interface
Instantiation
An interface is a type
List<String> names;
Instantiation
Instantiation
Instantiation
Instantiation
Abstract classes
abstract class
Abstract classes
Partial implementation
public abstract class AbstractCollection<E> ... {
...
public abstract int size();
public boolean isEmpty() {
return size() == 0;
}
public abstract Iterator<E> iterator();
public boolean contains(Object o) {
Iterator<E> iterator = iterator();
while (iterator.hasNext()) {
E e = iterator.next();
if (o==null ? e==null : o.equals(e)) return true;
}
return false;
}
}
Kozsik Tamás Programming languages Java 67 / 108
Generics Inheritance Interface Subtyping Cast
Abstract classes
Concrete subclass
public abstract class AbstractCollection<E> implements Collection<E>
...
public abstract int size();
}
Multiple inheritance
Multiple inheritance
Multiple inheritance
Examples
OK
package java.util;
public class Scanner implements Closeable, Iterator<String>
{ ... }
OK
interface PoliceCar extends Car, Emergency { ... }
Erroneous
class PoliceCar extends Car, Emergency { ... }
Multiple inheritance
Hypothetically
class Base1 {
int x;
void setX(int x) { this.x = x; }
...
}
class Base2 {
int x;
void setX(int x) { this.x = x; }
...
}
Multiple inheritance
class Base0 {
int x;
void setX(int x) { this.x = x; }
...
}
Multiple inheritance
Multiple inheritance
interface Base2 {
abstract void setX(int x);
...
}
Inheritance
• Code reuse
• Subtyping
Inheritance
𝐴 Δ 𝐵 ⇒ 𝐴 <∶ 𝐵
Inheritance
𝐴 Δ 𝐵 ⇒ 𝐴 <∶ 𝐵
public class ExactTime extends Time { ... }
• ExactTime has everything Time has
• Whatever you can do with Time, you can do with ExactTime
• ExactTime <∶ Time
Inheritance
𝐴 Δ 𝐵 ⇒ 𝐴 <∶ 𝐵
public class ExactTime extends Time { ... }
• ExactTime has everything Time has
• Whatever you can do with Time, you can do with ExactTime
• ExactTime <∶ Time
• ∀𝑇 class ∶ 𝑇 <∶ java.lang.Object
Inheritance
Subtyping
public class Time {
...
public void aMinutePassed() { ... }
public boolean sameHourAs(Time that) { ... }
}
Inheritance
Polymorphic references
public class Time {
...
public void aMinutePassed() { ... }
public boolean sameHourAs(Time that) { ... }
}
Dynamic binding
Dynamic binding
Dynamic binding
Overriding
package java.lang; // java.lang.Object@4f324b5c
public class Object {... public String toString() {...} ... }
Dynamic binding
Overriding
package java.lang; // java.lang.Object@4f324b5c
public class Object {... public String toString() {...} ... }
Dynamic binding
Overriding
package java.lang; // java.lang.Object@4f324b5c
public class Object {... public String toString() {...} ... }
Dynamic binding
Overloading
• Same name, different formal parameters
• Inherited methods can be overloaded (in Java!)
• Compiler selects method based on actual parameters
Overriding
• An instance method defined in a base class
• Same name, same formal parameters (same signature)
⋄ Same method
⋄ Multiple implementations
• The “most specific” implementation is selected at run time
Dynamic binding
System.out.println(e.toString()); // 0:00:00
System.out.println(t.toString()); // 0:00:00
System.out.println(o.toString()); // 0:00:00
At the invocation of an instance method, the implementation that matches
the dynamic type of the privileged parameter best will be selected.
Dynamic binding
Dynamic type
• Which implementation of an instance method?
Object o = new Time();
System.out.println(o); // select toString()
// implementation
• Dynamic type checking
Inheritance example
package company.hr;
public class Employee {
String name;
int basicSalary;
java.time.ZonedDateTime startDate;
...
}
Inheritance example
package company.hr;
public class Employee {
String name;
int basicSalary;
java.time.ZonedDateTime startDate;
...
}
package company.hr;
import java.util.*;
public class Manager extends Employee {
final HashSet<Employee> workers = new HashSet<>();
...
}
Parent class
package company.hr;
import java.time.ZonedDateTime;
import static java.time.temporal.ChronoUnit.YEARS;
public class Employee {
...
private ZonedDateTime startDate;
public int yearsInService() {
return (int) startDate.until(ZonedDateTime.now(), YEARS);
}
private static int bonusPerYearInService = 0;
public int bonus() {
return yearsInService() * bonusPerYearInService;
}
}
Child class
package company.hr;
import java.util.*;
public class Manager extends Employee {
// inherited: startDate, yearsInService() ...
...
private final Set<Employee> workers = new HashSet<>();
public void addWorker(Employee worker) {
workers.add(worker);
}
private static int bonusPerWorker = 0;
@Override public int bonus() {
return workers.size() * bonusPerWorker + super.bonus();
}
}
Dynamic binding
Type conversions
Type conversions
Wrapper classes
Type conversions
Type conversions
Auto-(un)boxing
Type conversions
Auto-(un)boxing
Type casting
Object
...
upcast downcast
Time
...
Type casting
Type casting
Type casting
Type casting
Type casting
instanceof operator
Type casting
instanceof operator
Type casting
instanceof operator
Type casting
Inheritance – subtyping
• class A extends B …
• 𝐴 <∶ 𝐵
• ∀𝑇 ∶ 𝑇 <∶ java.lang.Object
ClassCastException