CSA 1019 Imperative and OO Programming Object Oriented III Mr. Charlie Abela Dept. of of Artificial Intelligence
Objectives Getting familiar with Method Overriding Polymorphism Overriding Vs Vs Overloading Dynamic binding UpCasting and and DownCasting objects instanceof operator ArrayList and Vector Charlie Abela CSA1019: OOP III 2
Method Overriding Reconsider the the geometry hierarchy. The The method tostring() is is defined in in the the Shape class class and and overridden in in both both the the Rectangle and and the the Circle classes. Shape -colour:string = "white" -datecreated: java.util.date + Shape() +setcolour(col: String): void +getcolour(): String +getdatecreated():java.util.date +tostring():string Rectangle Circle -width:double = 1.0 -length:double = 1.0 +Rectangle() +Rectangle(w:double, l:double) +setwidth(w:double):void +getwidth():double +setlength(l:double):void +getlength():double +tostring():string +calculatearea():double -radius:double = 1.0 +Circle() +Circle(r:double) +setradius(r:double):void +getradius():double +tostring():string +calculatearea():double Charlie Abela CSA1019: OOP III 3
Method Overriding (cont) Method overriding involves the creation of of another method (in a subclass) which has the same signature, and its return type is is compatible with that of of the method in in the superclass. public class class Shape{ public String tostring(){ return This This is is a Shape Shape object ; public class class Square extends Shape{ public String tostring(){ return This This is is a Square object ; Charlie Abela CSA1019: OOP III 4
Method Overriding (cont) It It is is not possible to to override a method which is is marked as as final or or as as static The access level cannot be more restrictive than that of of the overridden method s. However it it can be less. In In essence, if if a method cannot be inherited for some reason, then it it cannot be overridden. Charlie Abela CSA1019: OOP III 5
Method Overriding (cont) Implementation of of tostring in in the Shape class public String tostring(){ return getcolour()+ shape created on on +getdatecreated(); Implementation of of tostring in in the Circle class public String tostring(){ return getcolour()+ Circle created on on +getdatecreated(); Therefore this is is possible Shape s = new new Shape(); Circle c = new new Circle(); s.tostring(); //invoke the the overriden version c.tostring(); Charlie Abela CSA1019: OOP III 6
Better use of overriding Re-implementation of of the tostring in in the Shape class public String tostring(){ return Colour: +getcolour()+ \n \n DateCreated: +getdatecreated(); Re-implementation of of the tostring in in the Circle class public String tostring(){ return Circle Details \n + \n + super.tostring(); In In this way the parent s tostring method is is reused in in an effective manner Charlie Abela CSA1019: OOP III 7
Overriding Vs Overloading public class class Test{ Test{ public static void void main(string[] args){ A a = new new A(); A(); a.p(10); public class class B{ B{ public void void p(int p(int i){ i){ System.out.println( B prints +i); +i); public class class A extends B{ B{ public void void p(int p(int i){ i){ System.out.println( A prints +i); +i); A prints 10 10 Charlie Abela CSA1019: OOP III 8
Overriding Vs Overloading public class class Test{ Test{ public static void void main(string[] args){ A a = new new A(); A(); a.p(10); public class class B{ B{ public void void p(int p(int i){ i){ System.out.println( B prints +i); +i); public class class A extends B{ B{ public void void p(double i){ i){ System.out.println( A prints +i); +i); B prints 10 10 Charlie Abela CSA1019: OOP III 9
Binding Consider the the following method invocation: obj.doit(); At At some point, this invocation is is bound to to the the definition of of the the method that it it invokes If If this binding occurred at at compilation time, then that line of of code would call the the same method every time However, Java defers method binding until run time -- -- this is is called dynamic binding or or late binding Late binding provides flexibility in in program design Charlie Abela CSA1019: OOP III 10
Polymorphism Means many forms It It is is the the ability to to treat an an object of of any subclass as as if if it it were an an object of of the the base/super class. A base class will therefore have many forms as as itself itself as as any any of of its its subclasses Polymorphism makes effective use of of dynamic binding or or late late binding Why is is polymorphism important? allows for for improved code code organisation and and readability for for creating extensible programs (generic programming): programs that that grow in in time time with with little little effect on on existing code code Charlie Abela CSA1019: OOP III 11
Example Shape Circle Rectangle Shape s = new new Shape(); through polymorphism the the following is is also possible Shape s1 s1 = new new Circle(); Shape s2 s2 = new new Rectangle(); This is is called upcasting (i.e. going from a subclass up, towards a superclass) Upcasting is is always possible since a subclass can always behave like its its superclass. Charlie Abela CSA1019: OOP III 12
Example (cont) Therefore this is is also possible Shape s1 s1 = new new Circle(); Shape s2 s2 = new new Rectangle(); s1.tostring(); s2.tostring(); s1.tostring() will invoke the Circle s tostring() method Circle Details Colour: white white DateCreated: 12/12/07 s2.tostring() will invoke the Rectangle s tostring() method Rectangle Details Colour: white white DateCreated: 12/12/07 Charlie Abela CSA1019: OOP III 13
Dynamic Binding The compiler checks the declared reference types at at compilation time, however the JVM checks the real object at at runtime. When the tostring method is is called via the Shape reference variable: the the JVM looks at at the the real objects at at the the other end of of the the reference, sees that the the method has been overridden by by both the the Circle and Rectangle classes and invokes the the method in in the the object s class. This is is also referred to to as as virtual method invocation Charlie Abela CSA1019: OOP III 14
Dynamic Binding II Dynamic binding works as as follows: Suppose an object o is is an instance of of classes C 1,, C 2,,..., C n-1 n-1,, and C n,, where C 1 is is a subclass of of C 2,, C 2 is is a subclass of of C 3,,..., and C n-1 n-1 is is a subclass of of C n.. C n is n is the the most general class C 1 is 1 is the the most specific class. In In Java, C n is n is the the Object class. If If o invokes a method p, p, the the JVM searches the the implementation for for the the method p in in C 1, 1, C 2, 2,..., C n-1 and n-1 C n, n, in in this order, until it it is is found. Once an an implementation is is found, the the search stops and the the first-found implementation is is invoked. Charlie Abela CSA1019: OOP III 15
Dynamic Binding III C n Object C n-1... C 2 C 1 Since o is an instance of C 1, o is also an instance of C 2, C 3,...C n -1 and C n. Charlie Abela CSA1019: OOP III 16
Polymorphism in Animals Animal Lion Cat Horse Wolf Dog Animal[] animals = new new Animal[5]; animals[0] = new new Dog(); animals[1] = new new Cat(); animals[2] = new new Wolf(); animals[3] = new new Horse(); animals[4] = new new Lion(); for(int i = 0; 0; i < animals.length; i++){ i++){ animals[i].eat(); Each Each object in in the the array array is is referenced by by a more more generic reference variable At At runtime, however, the the actual object is is seen seen by by the the JVM, and and the the appropriate object s eat eat method is is invoked. Charlie Abela CSA1019: OOP III 17
Polymorphic Arguments What happens in in this code? public class class Vet{ Vet{ public void void giveshot(animal a){ a){ //assume all all animals have have this this method a.makenoise(); public class class PetOwner{ public void void taketovet(){ Vet Vet v = new new Vet(); Dog Dog d = new new Dog(): Horse Horse h = new new Horse(); v.giveshot(d); v.giveshot(h); Dog s Dog s makenoise() invoked Horse s makenoise() invoked Charlie Abela CSA1019: OOP III 18
Polymorphic Arguments II What is is the output of of this code? public class class Animal{ public class class Horse Horse extends Animal{ public class class UseAnimals{ public void void dostuff(animal a){ a){ System.out.println( Animal version ); public void void dostuff(horse h){ h){ System.out.println( Horse version ); public static void void main(string[] args){ UseAnimals ua ua = new new UseAnimals(); Animal animalobj = new new Animal(); Horse Horse horseobj = new new Horse(); ua.dostuff(animalobj); ua.dostuff(horseobj); Animal version Horse Horse version Charlie Abela CSA1019: OOP III 19
Polymorphic Arguments II (cont) What if if an Animal reference is is assigned to to a Horse object? Animal animalref = new new Horse(); ua.dostuff(animalref); Which overloaded version is is invoked? Remember: Animal version The reference type determines which overloaded method is is invoked, at at compilation time The object type is is used to to determine which overridden version of of a method is is called at at runtime Charlie Abela CSA1019: OOP III 20
Overloaded and Overridden methods What happens when methods are both overloaded and overridden? public class class Animal{ public void void eat(){ System.out.println( Generic eating ); public class class Horse Horse extends Animal{ public void void eat(){ System.out.println( Horse eating hay ); public void void eat(string s){ s){ System.out.println( Horse eating + + s); s); Charlie Abela CSA1019: OOP III 21
Overloaded and Overridden methods II Method Invocation Animal a=new Animal(); a.eat(); Horse h = new Horse(); h.eat(); Animal ah= new Horse(); ah.eat(); Horse he= new Horse(); he.eat( apples ); Animal a2= new Animal(); a2.eat( treats ); Animal ah2= new Horse(); ah2.eat( Carrots ); Results Generic eating Horse eating hay Horse eating hay; due to polymorphism the actual object type is used to determine method Horse eating apples; overloaded eat(string s) method is invoked Compiler error! Compiler tries to find eat(string s) within Animal and fails Compiler error! Compiler still tries to find an eat(string s) in Animal and fails Charlie Abela CSA1019: OOP III 22
Downcasting In In the previous example the following code produced a compilation error Animal ah2= ah2= new new Horse(); ah2.eat( Carrots ); There is is however a solution Animal ah2= ah2= new new Horse(); ((Horse)ah2).eat( Carrots ); Downcast (explicit casting) the reference variable to to a Horse object and invoke its eat(string s) s) method. The compiler will not complain since he is is forced to to trust the developer Charlie Abela CSA1019: OOP III 23
Downcasting (cont) Explicit casting must be used when casting an object from a superclass to to a subclass. This type of of casting may not always succeed. Apple x = (Apple)fruit; Orange x = (Orange)fruit; Charlie Abela CSA1019: OOP III 24
Downcasting (cont) Downcasting could produce a ClassCastException if if not done correctly public class class Animal{ public class class Dog Dog extends Animal{ public class class DogTest{ public static void void main(string[] args){ Animal animal = new new Animal(); Dog Dog fido fido = (Dog)animal; Though this compiles, it it will fail at at runtime, giving an an exception, since we we are are trying to to downcast an an animal reference to to a Dog. However the the animal reference, was previously referring to to an an Animal object not a Dog object Charlie Abela CSA1019: OOP III 25
instanceof operator Use the instanceof operator to to check whether an object is is an instance of of a class or or not: Object myobject = new new Circle();...... // // Some Some lines lines of of code code /** /** Perform casting if if myobject is is an an instance of of Circle */ */ if if (myobject instanceof Circle){ System.out.println("The circle diameter is is " + ((Circle)myObject).getDiameter()); Charlie Abela CSA1019: OOP III 26
static methods Static methods (and data fields) cannot be be overridden. However they can be be redefined in in a subclass. A redefined static method (in (in the the subclass), hides the the static method in in its its parent class public class class Animal{ public static void void dostuff(){ System.out.print( a ); public class class Dog Dog extends Animal{ public static void void dostuff(){ System.out.print( b ); public static void void main(string[] args){ Animal[] a={new Animal(), new new Dog(); for(int i=0; i=0; i < a.length; i++) i++) a[i].dostuff(); a a Charlie Abela CSA1019: OOP III 27
ArrayList & Vector The ArrayList and Vector classes implement dynamic arrays. The two classes are very similar except for some performancerelated features. Both classes allow for adding, removing and accessing elements. Declaring/Initialising Vectors and ArrayLists Vector v = new new Vector(); Vector v2 v2 = new new Vector(10); ArrayList a = new new ArrayList(2); ArrayList<String> a = new new ArrayList<String>(); Charlie Abela CSA1019: OOP III 28
Adding/Accessing elements import java.util.arraylist; ArrayList a = new new ArrayList(); a.add("string"); a.add(1); //possible due due to to AutoBoxing a.add(2.3); //possible due due to to AutoBoxing for(int i=0; i=0; i< i< a.size(); i++){ i++){ System.out.println(a.get(i).toString()); a.remove(1); System.out.println(a.size()); System.out.println(a.contains(2.3)); Charlie Abela CSA1019: OOP III 29
Adding/Accessing elements import java.util.arraylist; ArrayList clist clist = new new ArrayList(); clist.add(new Circle(3.4)); clist.add(new Circle(4.5)); clist.add(new Circle(2.3)); for(int i=0; i=0; i < clist.size(); i++){ i++){ System.out.println( Area of of circle: + ((Circle)clist.get(i)).getArea()); import java.util.arraylist; ArrayList<Cat> cats cats = new new ArrayList<Cat>(3); cats.add(new Lion("micio")); cats.add(new Cheetah("runner")); cats.add(new Tiger("grahhh")); for(int i=0; i=0; i < cats.size(); i++){ i++){ //no //no need need to to typecast System.out.println(cats.get(i).getName()); Charlie Abela CSA1019: OOP III 30