POLYMORPHISM Generic programming! Code reuse: an algorithm can be applicable to many objects! Goal is to avoid rewri:ng as much as possible! Example: int sqr(int i, int j) { return i*j; double sqr(double i, double j) {return i*j;! The no:on of sqr is unique but we must define it twice because of types! Programming languages offer mechanisms to address this problem 1
Polymorphism! Polymorphism (Greek for many forms ) is the ability for code to be used with values of different types.! For example, a polymorphic func:on is one that can be invoked with arguments of different types.! A polymorphic datatype is one that can contain elements of different types. FORMS OF POLYMORPHISM 2
Subtype Polymorphism! Subtype polymorphism allows a term to have many types using the subsump:on rule (inheritance).! A func:on with argument τ can operate on any value with a type that is a subtype of τ. Ad Hoc Polymorphism! Ad- hoc polymorphism usually refers to code that appears to be polymorphic to the programmer, but the actual implementa:on is not.! A typical example is overloading: using the same func:on name for func:ons with different kinds of parameters. 3
Ad hoc polymprphism! There are actually mul:ple func:on implementa:ons (none being polymorphic) and the compiler invokes the appropriate one.! Ad- hoc polymorphism is a dispatch mechanism: the type of the arguments is used to determine (either at compile :me or run :me) which code to invoke. Parametric Polymorphism! Parametric polymorphism refers to code that is wripen without knowledge of the actual type of the arguments; the code is parametric in the type of the parameters.! Examples include polymorphic func:ons in ML (F#) and Java (C#) generics. 4
ML let rec map f l = match l with [] -> [] x::xs -> f(x) :: map f xs;; val map : ('a -> 'b) -> 'a list -> 'b list = <fun> map (function x -> x*10) [4;2;7];; - : int list = [40; 20; 70] ML let square = (fun x -> x*x) ;; val square : int -> int = <fun> Q: Why? 5
public class Point { protected final int x, y; private final String name; public Point(int x, int y){ this.x = x; this.y = y; name = makename(); Java protected String makename() { return "["+x+", "+y+"]"; public final String tostring() { return name; public class ColorPoint extends Point{ private final String color; public ColorPoint(int x, int y, String color){ super(x,y); this.color = color; protected String makename() { return super.makename() + ":" + color; public static void main(string [] args) { System.out.println(new ColorPoint(4, 2, "viola")); Q: What is program behaviour? public class Point { protected final int x, y; private final String name; public Point(int x, int y){ this.x = x; this.y = y; name = makename(); Java protected String makename() { return "["+x+", "+y+"]"; public final String tostring() { return name; public class ColorPoint extends Point{ private final String color; public ColorPoint(int x, int y, String color){ super(x,y); this.color = color; protected String makename() { return super.makename() + ":" + color; public static void main(string [] args) { System.out.println(new ColorPoint(4, 2, "viola")); Q: What is program behaviour? [4, 2]:null 6
Java(C#) Polymorphic Assignment! Let S be an ancestor of T! T is a subclass of S in the hierarchy! Upcas:ng: an object of type T is apached to a reference of type S! Downcas:ng: an object of type S is apached to a reference of type T! class Vehicle; class Car extends Vehicle; // car is a subtype of Vehicle Vehicle v =(Vehicle) new Car(); // upcas:ng Car c = (Car)new Vehicle(); // downcas:ng Cas:ng in Java! Upcas:ng is implicit o For primi:ve types, upcas:ng means assigning a smaller type to a larger compa:ble type " byte to short to int to long to float to double (long to float may actually lose precision) o For reference types, upcas:ng means assigning a subtype to a supertype, that is: " a subclass to superclass " an implementa:on of an interface X to that interface X " an interface X to the implementa:on of an ancestor of X! Downcas:ng must be explicit o can raise run:me excep:ons if it turns out to be impossible o No casts are allowed for reference types outside the inheritance hierarchy 7
Containers! Java Vector Vector v = new Vector(); v.addelement("pippo"); v.addelement(new Integer(2));! Vector API: Signature of addelement: void addelement(object x);! The argument has type Object because the container may contain any type of object Programming issues! Inser:ng an object in a vector we loose type informa:on! In our example we implicitly upcast from String to Object: v.addelement("pippo");! Extrac:ng the element with the wrong cast produces a run:me error: Integer i = (Integer)v.elementAt(0); 8
Programming Issues class Vector { Object[] v; int size; public Vector() { v = new Object[15]; size = 0; public addelement(object e) { if (size == v.length) { Object[] w = new Object[](2 * size); w.copy(v, 0, size); v = w; v[size++] = e;! We assume only assignment opera:ons and arrays: opera:on available on all objects Sort Method 9
Abstract as much as possible! Itera:ng over a collec:on Interface 10
Enumerator for Vector class VectorEnum implements Enumeration { int idx; Vector v; bool hasmoreelements() { idx < v.size(); Object nextelement() { return v.elementat(idx++); VectorEnum(Vector v) { idx = 0; this.v = v;? Is the enumerator up to date? 11
Event handling in GUI! Before Java 1.1 OO GUI frameworks were based on sub- typing! GUI can be easily described using generic programming: bupons are a subtype of control which is a special window! Containers of graphical widgets operates on controls, irrespec:ve of their types! Event dispatching and handling is dealt by virtual methods o hence by default is delegated to the super- type Java AWT Event Model 12
Event handling Limits of AWT Event Model! Generic programming in this case is quite elegant but inefficient! Propaga:on of events to a number of handlers, mostly useless! Prolifera:on of classes: one for each object with different behavior 13
Alterna:ve Java JDBC! Java DataBase Connec:vity is a specifica:on from Sun for accessing databases in Java! Interes:ng example of generic programming! It implements a driver architecture exploi:ng the mechanisms of JVM 14
Overall architecture! The java.sql package exposes only interfaces! The only class is DriverManager! Using the class constructor a driver register itself with the DriverManager! The programmer performs the following steps: o Load the database driver (a Java class) o Create a connec:on to a database (using DriverManager) o Obtain a Statement and execute the query o Enumerate the rows using a ResultSet JDBC example 15