CSE 114 – Computer Science I Polymorphism Red Bay, Labrador Inheritance Overview • Inheritance allows you to define a very general class then later define more specialized classes by adding new detail – the general class is called the base or parent class • The specialized class inherits all the properties of the general class – specialized classes are derived from the base class – they are called derived or child classes • After the general class is developed, you only have to write the "difference" or "specialization" code for each derived class • A class hierarchy: classes can be derived from derived classes (child classes can be parent classes) – any class higher in the hierarchy is an ancestor class – any class lower in the hierarchy is a descendent class Overriding Verses Overloading Overriding Overloading • Same method name • Same method name • Same signature • One method in ancestor, one in descendant • Different signature • Both methods can be in same class Polymorphism with methods/operators • Polymorphism: two or more methods or operators with the same name but different definitions – A polymorphic method or operator is said to be "overloaded" – Examples: • + (addition and concatenation) • multiple constructors – Example: public void setUpValue(int setValue) { if (setValue > 0 && setValue <= numFaces) upValue = setValue; } public void setUpValue() { upValue = 1; } Polymorphism – with classes • Polymorphic Object – an object variable that can refer to different types of objects at different points in time • Polymorphic references in Java can be created in 2 ways – Using inheritance – Using interfaces Derived Classes: a Class Hierarchy Person Student Undergraduate MastersDegree Employee Graduate PhD Faculty NonDegree Staff Apparent vs. Actual Type • Each constructed object has an apparent type and an actual type – due to the rules of polymorphism – only methods of an objects apparent type are available – Java guarantees the apparent type of any object is an ancestor of its actual type (or the same) – Ex: Vector v = new Vector(); // what are v’s apparent & actual types? Object o1 = v; // what are o1’s apparent & actual types? int[] a = {1, 2}; Object o2 = a; // what are o2’s apparent & actual types? • Remember where polymorphism is particularly important? – Method arguments & return statements in the Collections Interface java.util.Hashtable • A Hashtable maps keys to values – done by mapping Objects (usually Strings) to Objects – http://java.sun.com/j2se/1.5/docs/api/java/util/Hashtable.html • Ex: Hashtable dates = new Hashtable(); dates.put("TODAY", new GregorianCalendar()); dates.put("DDAY", new GregorianCalendar( 1944, Calendar.JUNE,6)); dates.put("ENDOFWORLD", new GregorianCalendar( 2004, Calendar.OCTOBER, 27)); … Object obj = dates.get("ENDOFWORLD"); Calendar whatDate = (Calendar)obj; DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM); String dateString = df.format(whatDate.getTime()); System.out.println(dateString); •OUTPUT: Oct 27, 2004 java.util.ArrayList class • ArrayList implements List – can be passed to any method that takes a List object, like: • Collections.binarySearch – uses Comparator for comparisons • Collections.reverseOrder • Collections.shuffle • Collections.sort – uses Comparable for comparisons • You could also define your own class that implements List – then define the 25 abstract methods in List public class Employee implements Comparable { private String name; private int salary; public Employee(String initName, int initSal) { name = initName; salary = initSal; } public String getName(){ return name; } public int getSalary() { return salary; } public void setSalary(int newSalary) { salary = newSalary; } public int compareTo(Object o) { Employee otherEmp = (Employee)o; if (this.salary == otherEmp.salary) return 0; else if (this.salary > otherEmp.salary) return 1; else return -1; } public String toString() { return name + ", $" + salary; } } Ex: Allowing Employees to be sorted by salary Using ArrayLists import java.util.*; public class CollectionsTester { public static void main(String[] args) { ArrayList staff = new ArrayList(); Employee e = new Employee("Joe",100000); staff.add(e); e = new Employee("Jane",200000); staff.add(e); e = new Employee("Bob",66666); staff.add(e); Collections.sort(staff); Employee lowestPaid = (Employee)staff.get(0); System.out.println(lowestPaid); } } •Output: Bob, $66666 Assignment Compatibility • You can not assign an object of an ancestor class to a variable of a derived class type Person joseph = new Person("Joseph"); Student sophomore = joseph; Syntax Error sophomore = (Student)joseph; Runtime Error ClassCastException • You can assign an object of a derived class to a variable of any ancestor type Student jane = new Student("Jane Doe"); Person doe = jane; OK Student janeDoe = (Student)doe; OK? • Using casting, you can assign an object of a base class to an object of a derived class if it was previously of that type Undergraduate class public class Undergraduate extends Student { private String level; public Undergraduate(String initName) { super(initName); level = "U1"; } public String getLevel(){return level; } public void setLevel(String changeLevel) { level = changeLevel; } } public class PolymorphismExample Polymorphism via { Inheritance public static void main(String[] args) { Undergraduate joeShmo = new Undergraduate("Joe Shmo"); Student joe = joeShmo; Person shmo = joeShmo; System.out.println(shmo.getName() + ", “ + joe.getGpa() + ", " + joeShmo.getLevel()); joe.setGpa(2.5); shmo.setAge(20); System.out.println(joeShmo.getName() + ", " + joeShmo.getGpa() + ", " + joeShmo.getAge()); OUTPUT: Joe Shmo, 0.0, U1 Joe Shmo, 2.5, 20 PolymorphismExample (continued) Undergraduate jane = new Undergraduate("Jane Doe"); jane.setLevel("U4"); Student doe = jane; Person janeDoe = doe; Undergraduate undergrad = (Undergraduate)janeDoe; System.out.println(undergrad.getName() + ", " + undergrad.getGpa() + ", " + undergrad.getLevel()); } } OUTPUT: Jane Doe, 0.0, U4 Polymorphism via Interfaces public interface KnowItAll { public String giveSolution(); } public class Boss implements KnowItAll { public String name; public Boss(String initName) { name = initName; } public String giveSolution() { return "Now listen here..."; } } InterfacePolymorphism Example public class InterfacePolymorphismExample { public static void main(String[] args) { Boss ceo = new Boss("Mr. Burns"); System.out.println(ceo.name + ": " + ceo.giveSolution()); ceo.name = "Mr. Smithers"; KnowItAll boss = ceo; System.out.println(boss.giveSolution()); Boss president = (Boss)boss; System.out.println(president.name + ": " + president.giveSolution()); } } OUTPUT: Mr. Burns: Now listen here... Now listen here... Mr. Smithers: Now listen here... Automatic Type Conversion public class AutoTypeConversionExample { public static boolean haveSameName(Person p, Student s) { return (p.getName().equals(s.getName())); } public static void main(String[] args) { Person john = new Person("John"); Person jonny = new Person("Jonny Doe"); Student doe = new Student("John"); Student johnDoe = new Student("Doe"); true System.out.println(haveSameName(john, doe)); ERROR System.out.println(haveSameName(john, jonny)); System.out.println(haveSameName(doe, johnDoe)); false } } Automatic type conversion from Student to Person Methods returning Objects • Many times you’ll see methods that return Object values • For example, inside Vector class: – public Object clone() – Public Object elementAt(int index) • You may be able to cast these values into other class types to place them in your variables • For example: Vector vector = new Vector(); Vector clonedVector = (Vector)vector.clone(); You must know what valid type casts are possible