Polymorphism Methods COMP 206 Geoff Holmes Bernhard Pfahringer
Polymorphism & Methods COMP 206 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 to. String() { 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 my. Dog = 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 my. Dog = new Dog(); • As generic as possible => more flexible code: Map<String, Object> my. Map = new Hash. Map<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 give. Shot(Animal a) { a. make. Noise(); } } class Pet. Owner { public void start() { Vet v = new Vet(); Dog d = new Dog(); Hippo h = new Hippo(); v. give. Shot(d); v. give. Shot(h); } }
How to stop overriding: • final declaration: – class: cannot extend/subcl� ass any further final public class String {. . } – method: cannot be overridden in subclasses class Cat { final public void make. Noise() {…} – field: cannot change value final int count = animals. length;
Overriding rules • Argument and return type must be the same: class Appliance { public boolean turn. On(); } class Toaster extends Appliance { public boolean turn. On(int level); // OVERLOADING }
Overriding rules • May NOT be less accessible: class Appliance { public boolean turn. On(); } class Toaster extends Appliance { protected boolean turn. On(); // 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 Array. List(); strings. add(“hello”); String word = (String) strings. get(0); • New (since 1. 5): List<String> strings = new Array. List<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 Array. List<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 Array. List<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 nonstudent onto the students list on the other hand, how do you write generic code then accepting lists of sub-types of Persons ? ? ?
Wildcards void print. Collection(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 draw. All(Collection<? extends Shape> c) { for(Shape shape: c) { shape. draw(); } } // again, only read access, allows collections of Shape or any sub type of Shape
- Slides: 23