polymorphism & methods comp206 geoff holmes & bernhard pfahringer (these slides: lots of...
TRANSCRIPT
Polymorphism & Methods
COMP206 Geoff Holmes & Bernhard Pfahringer
(these slides: lots of input from Mark Hall)
poly + morphos (greek) “many forms”
Overriding
• Subclass redefines a method:– different behaviour– or maybe modified behaviour
class Rectangle {public String toString() {
return “<Rectangle @ ”+x+”/”+y+” “+width+” by “+height+”>”;
}
Inheritance
• Subclasses inherit everything from superclasses, but cannot directly access private fields or methods, only public and protected ones.
• Can still access overridden methods:public void roam() { super.roam(); // some additional local stuff}
Inheritance: Is-A (not Has-A)
• B should extend A if “B is-A A”– Triangle Is-A Shape– Surgeon Is-A Medical Doctor
• Bathroom Has-A Tub– Tub is an instance variable of Bathroom
(Composition)
Code Inheritance
• Use inheritance to implement shared behaviour (code) only once!
• Always avoid code duplication!– easier to change (only one place),
especially when debugging
Polymorphism
• what happens when one declares and initializes a reference variable:
Dog myDog = new Dog();• allocate space for reference variable of
type Dog• allocate space for a new Dog object on
the heap (and initialize it)• point the reference to the new object
Polymorphism
• Reference type can be any super class or Interface implemented by actual type:Animal myDog = new Dog();
• As generic as possible => more flexible code:
Map<String,Object> myMap = new HashMap<String,Object>();
Polymorphism
Animal[] animals = new Animal[]{new Dog(), new Lion(), new Cat(), new Wolf(), new Hippo()};
for(Animal a: animals) {a.eat();
a.roam();}
Polymorphism
• Parameters/Arguments and return values can be polymorphic too:class Vet { public void giveShot(Animal a) { a.makeNoise(); }}class PetOwner { public void start() { Vet v = new Vet(); Dog d = new Dog(); Hippo h = new Hippo(); v.giveShot(d); v.giveShot(h); }}
How to stop overriding:
• final declaration:– class: cannot extend/subclass any further
final public class String { .. }– method: cannot be overridden in subclasses
class Cat {
final public void makeNoise() {…}– field: cannot change value
final int count = animals.length;
Overriding rules
• Argument and return type must be the same:
class Appliance {
public boolean turnOn();
}
class Toaster extends Appliance {
public boolean turnOn(int level);
// OVERLOADING
}
Overriding rules
• May NOT be less accessible:
class Appliance {
public boolean turnOn();
}
class Toaster extends Appliance {
protected boolean turnOn();
// illegal
}
Overloading
• Two (or more) methods with the same name but different argument lists (see code example)
• Usually best avoided, can be very confusing and counter-intuitive
Which method is executed
• Compile time: compiler ensures that method with appropriate signature (compile-time type info for arguments) exists in “compile-time” receiver class
• Runtime: given the actual runtime-type of the receiver, the most specific method of appropriate signature is located and executed
• ==> runtime types of arguments do NOT matter (again, see code examples)
Java Generics
(with input from Robi Malik)
Generic types for collections
• Old Java (1.4 and older):List strings = new ArrayList();
strings.add(“hello”);
String word = (String) strings.get(0);
• New (since 1.5):
List<String> strings = new ArrayList<String>();
strings.add(“hello”);
String word = strings.get(0);
Advantages
• Better readability
• Better type-safety: no casts (runtime checks), compiler can already catch problems
Writing your own generic code
public class Stack<E> { public void push(E element) { contents.add(element); } public E pop() { int top = contents.size()-1; E result = contents.get(top); contents.remove(top); return result; } private List<E> contents = new ArrayList<E>();}
Formal type parameter
public class Stack<E> { … }
– convention: Short (single-char) uppercase– can be used wherever a Type is needed– will be replaced with actual Type
Problems with sub-types
class Student extends Person { .. }
List<Student> students = new ArrayList<Student>();
List<Person> people = students;
// should this be possible? -> no
No, because
Person sam = new Person();
people.add(sam);
// if this was legal, we would have just sneaked a non-student onto the students list
on the other hand, how do you write generic code then accepting lists of sub-types of Persons ???
Wildcards
void printCollection(Collection<?> c) {
for(Object o: c) {
System.out.println(o);
}
}
// only read access (everything is an Object), but cannot add, because do not know correct type (except null, which is any type)
Bounded wildcards
public void drawAll(Collection<? extends Shape> c) {
for(Shape shape: c) {
shape.draw();
}
}
// again, only read access, allows collections of Shape or any sub type of Shape