Object Oriented Programming - Lesson 8: Polymorphism and generic programming - Trinh Thanh Trung

• Polymorphism • Downcasting and upcasting • Overloading • Method call binding • Generic programming I. DOWN CASTING UP CASTING rimitive type casting • Java performs automatic primitive type casting when: – Two types are compatible – The destination type is larger then the source type – Example: • int i; • double d = i; • We have to perform manual primitive type casting when: – Two types are compatible – The destination type is smaller then the source typ

pdf46 trang | Chia sẻ: candy98 | Lượt xem: 404 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Object Oriented Programming - Lesson 8: Polymorphism and generic programming - Trinh Thanh Trung, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
LESSON VIII. Polymorphism and generic programming Trinh Thanh TRUNG (MSc) trungtt@soict.hust.edu.vn 094.666.8608 Objectives • Master the polymorphism technique • Understand the Java generic programming Content • Polymorphism • Downcasting and upcasting • Overloading • Method call binding • Generic programming I. DOWN CASTING AND UP CASTING Primitive type casting • Java performs automatic primitive type casting when: – Two types are compatible – The destination type is larger then the source type – Example: • int i; • double d = i; • We have to perform manual primitive type casting when: – Two types are compatible – The destination type is smaller then the source type – Example: • int i; • byte b = i; byte b = (byte)i; Reference type casting • Java performs automatic reference type casting when: – Two types are compatible – The destination type extends from the source type Up casting Moving up the inheritance hierarchy Objects of derived class is viewed as objects of base class Automatically cast A B C Up casting • Substitute the reference of the sub class for the reference of the super class in the inheritance public class 2DShape { public void display() { System.out.println("2D Shape"); } } public class Point extends 2DShape { private int x, y; ... public void displayPoint(){ System.out.print(“Point”); } } // I ... Point point = new Point(); // 2 following statements are equivalent 2DShape shape = (2DShape) point; 2DShape shape = point; // II ... 2DShape shape = new Point(); 8 Up casting • Java always remember what an object really is during up casting public class 2DShape { public void display() {...} } public class Point extends 2DShape { public void displayPoint(){...} } ... Point point = new Point(); 2DShape shape = point; shape.display(); //OK shape.displayPoint(); //impossible to call public interface 2DShape { public void display(); } public class Point implements 2DShape { // interface’s methods public void display() {...} // class’ methods public void displayPoint(){...} } ... Point point = new Point(); 2DShape shape = point; shape.display(); //OK shape.displayPoint(); //impossible to call Exercise: Implicit subclass object to super class object conversion • Refer to a super class object with a super class reference – Example ? • Refer to a sub class object with a subclass reference – Example ? • Refer to a sub class object with a super class reference is safe, but such code can only refer to super class members – Example ? • Refer to a super class object with a subclass reference is a syntax error – Example ? Up casting example public class Test1 { public static void main(String arg[]){ Person p; Employee e = new Employee(); p = e; p.setName(“Hoa”); p.setSalary(350000); // compile error } 10 Up casting example class Manager extends Employee { Employee assistant; // ... public void setAssistant(Employee e) { assistant = e; } // ... } public class Test2 { public static void main(String arg[]){ Manager junior, senior; // ... senior.setAssistant(junior); } } 11 Up casting example public class Test3 { String static teamInfo(Person p1, Person p2){ return "Leader: " + p1.getName() + ", member: " + p2.getName(); } public static void main(String arg[]){ Employee e1, e2; Manager m1, m2; // ... System.out.println(teamInfo(e1, e2)); System.out.println(teamInfo(m1, m2)); System.out.println(teamInfo(m1, e2)); } } 12 Reference type casting • We have to perform manual reference type casting when: – two types are compatible – The source type extends from the destination type Down casting Move back down the inheritance hierarchy Objects of base class is viewed as objects of derived class NOT automatically cast A B C Downcasting • Substitute the reference of the super class for the reference of the sub class in the inheritance hierarchy.  May not always suceed 14 public class 2DShape { public void display() { System.out.println("2D Shape"); } } public class Point extends 2DShape { private int x, y; ... public void displayPoint(){ System.out.print(“Point”); } } ... Point point = new Point(); 2DShape shape = point; if (shape instanceof 2DShape){ Point tempObj= (Point)shape; // 2 tempObj.displayPoint(); //possible to call } ... 2DShape shape = new Point(); Point point = (Point) shape; // 1 point.displayPoint(); //possible to call Type Compatibility • Does it work ? Syntax error • How can you make it work without changing the classes definitions? public class 2DShape { public void display() { System.out.println("2D Shape"); } } public class Circle extends 2DShape{ public static final double PI = 3.14159; private Point p; private double r; //radious ... public void changeRadious(double rad){ r = rad; } } ... Circle circle = new Circle(); 2DShape shape = circle; shape.changeWidth(20); ... Circle circle = new Circle(); 2DShape shape = circle; ((Circle)shape).changeRadious(20); //ok Problem with casting • Does it work ?  Runtime exception public class 2DShape { public void display() {...} } public class Circle extends 2DShape{ public static final double PI = 3.14159; private Point p; private double r; //radious ... public void changeRadious(double rad){...} } public class Point extends 2DShape { private int x, y; ... public void displayPoint(){...} } Point point = new Point(); Circle circle = new Circle(); TwoDimensionShape shape = circle; ((Point)shape).displayPoint(); Down casting example public class Test2 { public static void main(String arg[]){ Employee e = new Employee(); Person p = e; // up casting Employee ee = (Employee) p; Manager m = (Manager) ee; //run-time err Person p2 = new Manager(); Employee e2 = (Employee) p2; } } 17 II. POLYMORPHISM 1. Example Polymorphism • Polymorphism means “many different forms” of objects – The ability of a reference variable to change behavior according to what object instance it is holding. • Objects of different subclasses are treated as objects of a single super class • Java choose the correct overridden method in the appropriate sub class associated with the object Example • An operation that can be performed on a 2DShape object can also be performed on an object of one of three classes Triangle, Circle, Quadrilateral. – The super class 2DShape defines the common interface – The subclasses Triangle, Circle, Quadrilateral have to follow this interface (inheritance), but are also permitted to provide their own implementations (overriding) Shape 2D Shape 3D Shape Circle Triangle Quadrilateral Sphere Polyhedron Object .  Once a method is requested through the 2DShape class reference, the objects 2DShape, Triangle, Circle and Quadrilateral respond differently Example public class Circle extends 2DShape{ public static final double PI = 3.14159; private Point p; private double r; //radious ... public void display(){ System.out.print("Circle: " + r + ","); p.display(); System.out.println(); } } public class Quadrilateral extends 2DShape { private Point p1, p2, p3, p4; ..... public void display(){ System.out.println("Quadrilateral: "); p1.display(); p2.display(); p3.display(); p4.display(); System.out.println(); } } public class 2DShape { public void display() { System.out.println("2D Shape"); } } public class Point extends 2DShape { private int x, y; ... public void display(){ System.out.print("(" + x + "," + y + ")"); } } Example • There are many choice once a method is invoked through a super class reference. 22 Application program 2DShape display() Object of super class display() display() Object of Circle class Object of Quadrilateral class Circle: 1, (0,0) Quadrilateral: (0,0), (0,1), (1,0), (1,1) display() Object of Point class (0,1) 2D Shape Example 1 public static void handleShapes(Shape[] shapes){ for( int i = 0; i < shapes.length; ++i) { shapes[i].draw(); } for( int i = 0; i < shapes.length; ++i) { shapes[i].erase(); } } Example 2 public class Test3 { public static void main(String args[]){ Person p1 = new Employee(); Person p2 = new Manager(); Employee e = (Employee) p1; Manager m = (Manager) p2; } } Person p1 = new Person(); Person p2 = new Employee(); Person p3 = new Manager(); // ... System.out.println(p1.getDetail()); System.out.println(p2.getDetail()); System.out.println(p3.getDetail()); Example 3 class EmployeeList { Employee list[]; ... public void add(Employee e) {...} public void print() { for (int i=0; i<list.length; i++) { System.out.println(list[i].getDetail()); } } ... EmployeeList list = new EmployeeList(); Employee e1; Manager m1; ... list.add(e1); list.add(m1); list.print(); instanceof operator public class Employee extends Person {} public class Student extends Person {} public class Test{ public doSomething(Person e) { if (e instanceof Employee) {... } else if (e instanceof Student) {... ){ } else {...} } } III. GENERIC PROGRAMMING What is generic programming ? • Generic programming: creation of classes and methods that work in the same way on different types of objects – Generics with inheritance – Generics with type parameters: programming with classes and methods parameterized with types Up casting • C/C++: Use void pointer • Java: Use up casting • Example: equals() method class MyValue { int i; public boolean equals(Object obj) { return (this.i == ((MyValue) obj).i); } } public class EqualsMethod2 { public static void main(String[] args) { MyValue v1 = new MyValue(); MyValue v2 = new MyValue(); v1.i = v2.i = 100; System.out.println(v1.equals(v2)); System.out.println(v1==v2); } } Generic class • Syntax modifier class generic_class_name { // instance variable // constructor // methods } • Example: public class Information { private T value; public Information(T value) { this.value = value; } public T getValue() { return value; } } Example: Type arguments .... // Can be instantiated with class or interface type: Information string = new Information("hello"); //ok Information circle = new Information(new Circle()); Information shape = new Information(new 2DShape()); // Cannot use a primitive type as a type variable Information integer = new Information(2012); // failed // Use corresponding wrapper class instead Information integer = new Information(2012); //ok public class Information { private T value; public Information(T value) { this.value = value; } public T getValue() { return value; } } Type parameter naming convention Type Variable Name Meaning E Element type in a collection K Key type in a map V Value type in a map T General type S, U Additional general types Generic methods • Method introducing its own type parameters • Can be defined inside either generic or non- generic classes • Can be either static or non static • Syntax: modifier return_type method_name(parameters_list) { } • Example: public static void print(E[] a) { } Example public class ArrayTool { // method, printing all elements of a string array public static void print(String[] a) { for (String e : a) System.out.print(e + " "); System.out.println(); } // generic method, printing all array elements of different types public static void print(E[] a) { for (E e : a) System.out.print(e + " "); System.out.println(); } } ... Point[] p = new Point[3]; String[] str = new String[5]; int[] intnum = new int[2]; ArrayTool.print(p); ArrayTool.print(str); // can not call generic method with primitive types ArrayTool.print(intnum); Bounded Type Parameters • Bound: limits the parameter types that may be applied to a generic type – Class – Interface • Single bound: • Multiple bounds: Example public class Information { private T value; public Information(T value) { this.value = value; } public T getValue() { return value; } } ... Information pointInfo = new Information(new Point()); //OK Information stringInfo = new Information(); // error Example public class ShapeInfo { private T t; public void set(T t) { this.t = t; } public T get() { return t; } public void inspect(U u){ System.out.println("T: " + t.getClass().getName()); System.out.println("U: " + u.getClass().getName()); } } ... ShapeInfo pointInfo = new ShapeInfo(); ShapeInfo stringInfo = new ShapeInfo(); pointInfo.set(new Point()); // OK stringInfo.set(new Point()); // error: this is not a string pointInfo.inspect(new Circle()); // OK stringInfo.inspect(new Point()); // OK pointInfo.inspect("some text"); // error: this is not a 2DShape stringInfo.inspect("some text"); // erroe: this is not a 2Dshape Type erasure: generics class • Java compiler erases all type parameters and replaces each with: – Object (if the type parameter is unbounded) – its first bound (if the type parameter is bounded), or public class ShapeInfo { private T t; public void set(T t) { this.t = t; } public T get() { return t; } } public class ShapeInfo { private Object t; public void set(Object t) { this.t = t; } public Object get() { return t; } } public class Information { private T value; public Information(T value) { this.value = value; } public T getValue() { return value; } } public class Information { private 2DShape t; public void set(2Dshape t) { this.t = t; } public 2DShape get() { return t; } } Type erasure: generics method • Java compiler erases all type parameters and replaces each with: – Object (if the type parameter is unbounded) – its first bound (if the type parameter is bounded), or public static void print(E[] a) { for (E e : a) System.out.print(e + " "); System.out.println(); } public static void print(Object[] a) { for (Object e : a) System.out.print(e + " "); System.out.println(); } public void inspect(U u){ System.out.println("T: " + t.getClass().getName()); System.out.println("U: " + u.getClass().getName()); } public void inspect(2DShape u){ System.out.println("T: " + t.getClass().getName()); System.out.println("U: " + u.getClass().getName()); } Wildcard types • Wildcard (?) : unknown type Name Syntax Meaning Wildcard with lower bound ? extends B Any sub type of B Wildcard with higher bound ? super B Any super type of B Unbounded wildcard ? Any type Review • Polymorphism: – multiple objects of different subclasses to be treated as objects of a single super class • Type casting: – Up casting:sub class is type-cast to a super class – Down casting: super class is type-cast to a sub class • Overloading: methods in the same class are distinguished by their signature – Overloading constructors: creating objects in different ways • Method call binding: – Static binding: Method call is decided at compile-time – Dynamic binding: Method call is decided at run-time Review • Generic programming – Generic class / interface: parameterized over types – Generic method: introduce its own type parameters – Bound: constraint on the type of a type parameter – Type erasure: no new classes are created for parameterized types • Unbounded type parameters: replaced by Object • Bounded type parameters: replaced by bounds – Wildcard: unknown type of parameter, field, or local variable, unknown return type Quiz • Given 3 classes as follow: • Does the following code work ? Why ? public class 2DShape { public void toString() {...} } public class Circle extends 2DShape{ public static final double PI = 3.14159; private Point p; private double r; //radious ... public void toString(){...} } public class Point extends 2DShape { private int x, y; ... public void toString(){...} } Circle c = new Circle(5); Rect r = new Rect(5, 3); Shape s = null; if( Math.random(50) % 2 == 0 ) s = c; else s = r; System.out.println( "Shape is + s.toString()); Quiz • Given 3 classes as follow: • The method toString() is overridden. Which version gets called ? public class 2DShape { public void toString() {...} } public class Circle extends 2DShape{ public static final double PI = 3.14159; private Point p; private double r; //radious ... public void toString(){...} } public class Point extends 2DShape { private int x, y; ... public void toString(){...} } Circle c = new Circle(5); Rect r = new Rect(5, 3); Shape s = null; if( Math.random(50) % 2 == 0 ) s = c; else s = r; System.out.println( "Shape is + s.toString()); Quiz • Consider the following code • Which one is correct ? public class Pair { public T first; public U second; public Pair (T x, U y) { first = x; second = y; } public Pair () { first = null; second = null; } } 1. Pair pair = new Pair(); 2. Pair pair = new Pair(); 3. Pair pair = new Pair(0, new Circle()); 4. Pair pair = new Pair(new Circle()); Quiz • Which is the raw class of the following code: • Answer public class Pair { public T first; public U second; public Pair (T x, U y) { first = x; second = y; } public Pair () { first = null; second = null; } } public class Pair { public Object first; public Object second; public Pair (Object x, Object y) { first = x; second = y; } public Pair () { first = null; second = null; } }