Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Tirgul 8 Inheritance and Polymorphism 1 Inheritance and Polymorphism An important part of Object Oriented Programming. Very often misused by beginners. Inheritance: If the parent can do something, so can the child. Allows for code re-use (not as important as other traits – there are other ways we’ve seen to re-use code) Polymorphism: The ability to write code that works for many types. Inheritance enables this. This is the main benefit. Examples will follow… 2 Class hierarchy example Car PrivateCar Toyota Mazda CommercialCar … Subaru … Mazda121 Mazda323 … Mazda626 PrivateCar is a type of Car. It does anything Car does, and more. We say that PrivateCar extends Car. 3 Extending a class public class Car {…} public class PrivateCar extends Car{…} You can only extend one class. The extended class is often called: Parent Class, Super Class, Ancestor, Base Class. The extending class is called: Child, SubClass, Descendent, Derived Class. 4 Inheritance When a class extends another class it automatically inherits all of its members (Both methods and fields). However, it can access only the public and protected members. Implication: Child class can handle any method call that Parent class can. There is no way to “hide” any of the inherited methods. Car car = new Car(); PrivateCar privCar = new PrivateCar(); If you can do car.honk(); You can also do privCar.honk(); 5 Constructors and the keyword super The parent class has fields that must be initialized during creation of the child class. Therefore: any time a constructor of the child is called, the constructor of the parent is also called. Accomplished with: super() They may even be private and not accessible to the child. Must be the first statement in the constructor. If you do not use super() Java calls the default constructor of the parent. If there is no default, the code will not compile! 6 Extending a class Other Classes Public Public Protected Protected Private Private Parent Class Child Class 7 Example No one except the class Person can initialize the field _name. public class Person{ private final String _name; public Person(String name){ _name = name; } public String getName(){ return _name;} } because it is final, initialization of _name must occur at creation time. public class CSStudent extends Person{ private String _login; public CSStudent(String name, String login){ super(name); _login = login; } } 8 Upcasting We can always treat a child object as if it were a parent object Upcasting is converting from child type to parent type (always safe) PrivateCar prvCar = new PrivateCar(); explicit upcasting Car car1 = (Car) prvCar; Car car2 = prvCar; implicit upcasting car1.honk(); car2.honk(); 9 Downcasting Downcasting is converting from parent type to child type (not always safe!) Downcasting must always be explicit Car car1 = PrivateCar PrivateCar Car car2 = PrivateCar new PrivateCar(); implicit upcasting prvCar = car1; implicit downcasting: compile error prvCar1 = (PrivateCar) car1; new Car(); downcasting - OK prvCar2 = (PrivateCar) car2; This will cause a runtime ClassCastException: Car cannot be converted to PrivateCar 10 Why upcast? Suppose you want to built a data structure that could only hold Strings. What if we want to hold something else? Do we write a new structure for every type of object we create? Instead: write a structure that holds java.lang.Object use upcasting when putting in values, and downcasting when extracting. 11 Upcasting and Downcasting public class MyStructure{ private Object[] _data; public Insert(Object element){…} public Object Remove(){…} … } Somewhere else in the code: String str = “Hello”; struct.insert(str); //upcasting str = (String) struct.remove(); //downcasting Is it safe to downcast here? 12 instanceof What if we mix items of different types in the structure and wish to downcast correctly? We can check the exact type of the class using the keyword “instanceof” Object item = struct.remove(); if(item instanceof String){ String str = (String) item; //this is safe! ... } 13 instanceof (a instanceof B) is true iff a is an instance of class B or any of its descendants Car car = new Car(); System.out.print(car instanceof Object); true System.out.print(car instanceof Car); true System.out.print(car instanceof PrivateCar); false 14 How not to use instanceof Our code should be designed so that adding new child classes does not necessitate changes to the parent class Do not do this: public class PrivateCar { public void print() { if (this instanceof Mazda) System.out.print(“Mazda”); if (this instanceof Toyota) System.out.print(“Toyota”); } } Instead: use method overriding… 15 Overriding methods Objects inherit methods from their parent, but may change the methods they inherit. Simply redefine them. The keyword super can be used to call methods from the parent class and thus reuse their code. public class CSStudent extends Person{ private String _login; ... public String getName(){ return super.getName() + “ “+ _login; } } 16 Polymorphism The inheritance mechanisms we’ve seen allow using objects that have a shared ancestor interchangeably We do not need to know the exact type of the object we are holding The “correct” implementation of overridden methods will be called at runtime 17 Polymorphic use of objects All the mechanisms we’ve just seen give us power to use objects that have a shared ancestor interchangeably. We do not need to know the exact type of object we are holding. Example: public class Animal(){ public void makeSound(){} … } 18 Subclasses of animal. public class Dog extends Animal{ public void makeSound() { System.out.println("Woof Woof"); } } public class Cat extends Animal{ public void makeSound() { System.out.println("Meow"); } } public class Bird extends Animal{ public void makeSound() { System.out.println(“Tweet Tweet"); } } 19 public static void main(String[] args){ Animal[] animals = new Animal[3]; animals[0] = new Dog(); animals[1] = new Cat(); animals[2] = new Bird(); for(int i=0; i<animals.length; i++){ animals[i].makeSound(); } } This last bit of code can treat all kinds of animals. Even those that are not written yet. Output: Woof Woof Meow Tweet Tweet 20 Abstract classes & methods Abstract methods have no implementation. They must reside inside abstract classes If the child class is not abstract, it must implement all abstract methods. Abstract classes cannot be instantiated. Useful for things we don’t want an instance of. They may still have constructors. (What for?) 21 Abstract Animal We do not want anyone to create an object out of the Animal class. We make it abstract: public abstract class Animal(){ public abstract void makeSound(); … } We also turned makeSound() into an abstract method because we want all subclasses to implement it But cannot offer a “default” implementation that is inherited. 22 Abstract - Example abstract class Shape { Notice the abstract abstract void draw() ; method declaration abstract void erase(); abstract double area(); } class Circle extends Shape { void draw() { System.out.println("Circle.draw()"); } void erase() { System.out.println("Circle.erase()"); } double area(){ System.out.println(“pi*r^2"); … } } 23 Abstract - Example (cont.) class Square extends Shape { void draw() { System.out.println("Square.draw()"); } void erase() { System.out.println("Square.erase()"); } double area(){ System.out.println(“base*height"); … } } class Triangle extends Shape { void draw() { System.out.println("Triangle.draw()");} void erase() { System.out.println("Triangle.erase()“);} double area() { System.out.println("Triangle area…"); … } } 24 Random shapes generator // A "factory" that randomly creates shapes class RandomShapeGenerator { public Shape next() { int randNum=(int) Math.random()*3; switch(randNum) { case 0: return new Circle(); break; case 1: return new Square(); break; case 2: return new Triangle(); break; default: break; } } } 25 Casting and arrays public class Shapes { private static RandomShapeGenerator gen = new RandomShapeGenerator(); public static void main(String[] args) { Shape[] s = new Shape[9]; We don’t know what shapes are // Fill up the array with shapes: created and for(int i = 0; i < s.length; i++) inserted to s s[i] = gen.next(); // Make polymorphic method calls: for(int i = 0; i < s.length; i++) s[i].draw(); } } Polymorphism! (No explicit casting and no ‘instance of’ check are needed) 26 Polymorphism and arrays – typical run >> Square.draw() Circle.draw() Triangle.draw() Square.draw() Triangle.draw() Circle.draw() Square.draw() Square.draw() Square.draw() 27 Interfaces Not the same interface we talk about when we discuss API. Rather: a java construct (similar to a class). 28 Interfaces The most frequent use of polymorphism is usually via interfaces. They are like abstract classes with all methods abstract. The difference: An object can implement several interfaces. 29 Interface syntax public interface CanCopy { public Object copy(); } Place this in a file named CanCopy.java public interface Printable { public void print(); } Place this in a file named Printable.java public class Child extends Parent implements CanCopy, Printable { public Object copy() {…} public void print() {…} … } 30 public Interface Closeable{ public void close(); } Place this in Closeable.java. Notice there is no implementation of close() public class Child extends Parent implements Closeable{ public void close(){} This class must implement } all methods in the interface, or be abstract. Public class A extends B implements C,D,E{ … Promises to implement } several interfaces. 31 Example: Comparable This interface imposes an ordering on the objects of each class that implements it public interface Comparable { /** Compares this object with the given object. Returns a negative integer, zero, or a positive integer if this object is smaller, equal, or larger than the given object. */ public int compareTo(Object obj); } 32 Implementing Comparable We will compare people based on their weight public class Person implements Comparable { private int _weight; private String _name; What will happen if public int compareTo(Object obj) { someone tries to compare Person other = (Person) obj; a Person to an object if (_weight == other._weight) which is not a Person? return 0; return _weight < other._weight ? -1 : 1; } … } 33 Using Comparable: findMax We can use this method on an array of any type of objects which implement the Comparable interface /** Returns the maximal item in a given array */ public static Comparable findMax (Comparable[] items) { Comparable max = items[0]; for (int i=1; i<items.length; i++) { if (max.compareTo(items[i]) < 0) { max = items[i]; } What are this method’s assumptions? } return max; } 34 Using findMax public static void printFattest(Person[] people) { Person fattest = (Person) findMax(people); System.out.print(“The fattest person is “ + fattest.getName() + “, weighing “ + fattest.getWeight() + “ kg!”); } What if we sometimes want to compare people based on different criteria? 35 Iterator Similarly to DigitsParser (from Ex. 3), we can define a general iterator. This iterator can iterate over a collection (and not only string). public interface Iterator { public Comparable next(); public boolean hasNext(); } 36 Implementing the interfaces: Now, every class that would like to implement iterator will have to “stick” the Iterator interface description. public class DigitsIterator implements Iterator{ public boolean hasNext() {...} public Comparable next() {...} ... } 37 Now we can write code that fits any data structure: public static boolean isInside(Iterator iter, Comparable item){ while(iter.hasNext()){ if (iter.next().compareTo(item)==0){ return true; } } return false; } This will work for any iterator, regardless of the data structure it is linked to. 38 The Comparator interface This interface will be implemented by objects that know how to compare other objects public interface Comparator { /** Compares two objects. Returns a negative integer, zero, or a positive integer if obj1 is smaller, equal, or larger than obj2. */ public int compare(Object obj1, Object obj2); } 39 Implementing Comparator (1) This class compares people based on their weight public class PersonWeightComparator implements Comparator { public int compare(Object obj1, Object obj2) { Person person1 = (Person) obj1; Person person2 = (Person) obj2; int weight1 = person1.getWeight(); int weight2 = person2.getWeight(); if (weight1 == weight2) return 0; return weight1 < weight2 ? -1 : 1; } } 40 Implementing Comparator (2) This class compares people based on their name public class PersonNameComparator implements Comparator { public int compare(Object obj1, Object obj2) { Person person1 = (Person) obj1; Person person2 = (Person) obj2; String name1 = person1.getName(); String name2 = person2.getName(); return name1.compareTo(name2); } Class String implements the java.lang.Comparable } interface, comparing strings lexicographically 41 findMax using Comparator Now this method may give different results for the same array, based on the given Comparator /** Returns the maximal item in a given array */ public static Object findMax (Object[] items, Comparator comp) { Object max = items[0]; for (int i=1; i<items.length; i++) { if (comp.compare(max, items[i]) < 0) { max = items[i]; } } return max; } 42 Using findMax with a Comparator public static void printFattest(Person[] people) { Comparator comp = new PersonWeightComparator(); Person fattest = (Person) findMax(people, comp); System.out.print(“The fattest person is “ + fattest.getName() + “, weighing “ + fattest.getWeight() + “ kg!”); } 43 Using findMax with a Comparator public static void printFirst(Person[] people) { Comparator comp = new PersonNameComparator(); Person first = (Person) findMax(people, comp); System.out.print(“The person whose name “ + “comes first alphabetically is “ + first.getName()); } 44 Misc. Notes on Inheritance 45 Interfaces can extend interfaces We can have inheritance within interfaces. public interface A{ ... } public interface B extends A{...} public class C implements B{...} Now, everyone that implements B, must also implement all of A’s methods. C obj = new C(); B obj2 = obj; //upcasting A obj3 = obj; //upcasting 46 Reminder: Casting and arrays Arrays can be cast to parent types and back. public static void main(String[] args){ Object[] objArr = new String[5]; Upcasting objArr[0] = "Hi"; System.out.println(objArr instanceof String[]); String[] strArr = (String[]) objArr; System.out.println(strArr[0]); Downcasting } 47 final classes and methods A final method cannot be overridden. A final class cannot be extended. For example, you may want to declare methods that are called from a constructor final, so they are not changed by accident by extending classes. 48 Static methods are inherited but aren’t polymorphic! public class Parent { public static void myMethod(){ System.out.println("Parent"); } } public class Child extends Parent { public static void myMethod(){ System.out.println(“Child"); } } public static void main(String[] args){ Parent obj = new Child(); obj.myMethod(); } Output: Parent 49 When to extend and when to reference? Sometimes we have objects that use other objects. Sometimes we have objects that extend other objects. When do we use each method? public class Person{ public Person(String name){…} public String getName(){…} public Person[] getListOfFriends(){…} } 50 When to extend and when to reference? public class Car { Car _driver private Person _driver; public Car(Person driver, double topSpeed){ _driver = driver; Person } public String getDriverName(){…} Can both classes do the public double getTopSpeed(){…} same things? Yes! } Which is better? public class Car extends Person{ public Car(String driverName, double topSpeed){ super(driverName); _topSpeed = topSpeed; } public double getTopSpeed(){…} } Person Car 51 When to extend and when to reference? Extend mostly when you want to use objects interchangeably. Otherwise you may inherit methods that are not sensible No way to hide methods… Usually, you should reference. 52 Collection interface Collection is an abstract representation of a … collection/group of items/elements – an object that holds other objects (also called container). Typically, collections are iterable. Elements in a collection have no specific order. Queue, stack, arrays, sets and many other more data structures (to be learnt in the next semester/year) can be implemented using the collection interface. Check the interface for the Collection type in Java. (http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collection.html ) 53 Partial interface for collection Public interface Collection { public boolean add (Object o); public boolean contains(Object o); public boolean isEmpty(); public boolean remove(Object o); public Iterator iterator(); public Object[] toArray(); There are no guarantees } concerning the order in which Elements are returned in the same order of the iterator the elements are returned (unless this collection is an instance of some class that provides a guarantee) 54 Call by Reference vs. Call by Value – Test Yourselves public void swap0(int a, int b){ int temp = a; a = b; b = temp; } public void swap1(int[] a, int[] b){ int[] temp =a; a = b; b = temp; } Which of these is useless? 55 Call by Reference vs. Call by Value – Test Yourselves public void swap2(int[] a, int[] b){ int[] temp =a.clone(); a = b.clone(); b = temp; } public void swap3(int[] a, int[] b){ for(int i=0; i<a.length; i++){ int temp = a[i]; a[i] = b[i]; b[i] = temp; } } Which of these is useless? 56