Reusable components act on many types. In Java, this is often supported by operating on the class Object, but this requires a great deal of casting, which can be awkward and error prone. To illustrate, here is a sorter in Java, followed by the same program in Pizza.
In the Java program, the marked line will fail at run time, because a comparator for integers is used with strings. In the corresponding Pizza program, the same line will cause an error at compile time (and so the whole line itself is commented out).
Also, note that in the Java program, for sorting purposes one must use
an array of Integer
not an array of int
, since
Integer
(but not int
) is a subclass of Object
.
Pizza can work with the int
type directly. (It does this by
using a special representation for arrays of polymorphic type, and by
automatically packing an int
as an Integer
when an
Object
is expected.)
Example 2.1 Sort in Java.
abstract class Ord { public abstract boolean leq (Object x, Object y); } class OrdInteger extends Ord { public boolean leq (Object x, Object y) { return ((Integer)x).intValue() <= ((Integer)y).intValue(); } } class OrdString extends Ord { public boolean leq (Object x, Object y) { return (((String)x).compareTo((String)y) <= 0); } } class Sort { static void sort (Ord p, Object[] a) { for (int i = 0; i < a.length; i++) { for (int j = i+1; j < a.length; j++) { if (!p.leq(a[i],a[j])) { Object t=a[i]; a[i]=a[j]; a[j]=t; } } } } public static void main(String[] args) { Integer[] a = { new Integer(2), new Integer(1) }; sort(new OrdInteger(), a); String[] b = {"data", "ditto", "dada"}; sort(new OrdString(), b); sort(new OrdInteger(), b); /* RUN-TIME ERROR */ } }
Example 2.2 Sort in Pizza
abstract class Ord<T> { public abstract boolean leq (T x, T y); } class OrdInteger extends Ord<int> { public boolean leq (int x, int y) { return x <= y; } } class OrdString extends Ord<String> { public boolean leq (String x, String y) { return x.compareTo(y) <= 0; } } class Sort { static <T> void sort (Ord<T> p, T[] a) { for (int i = 0; i < a.length; i++) { for (int j = i+1; j < a.length; j++) { if (!p.leq(a[i],a[j])) { T t=a[i]; a[i]=a[j]; a[j]=t; } } } } public static void main(String[] args) { int[] a = {2, 1}; sort(new OrdInteger(), a); String[] b = {"data", "ditto", "dada"}; sort(new OrdString(), b); /* sort(new OrdInteger(), b); COMPILE-TIME ERROR */ } }