1 / 18

Generics

Generics. Example. Stack<E> + Stack<E> () + boolean isEmpty () + void push (E z) + E pop () + E peek (). Stack<String> s1 , s2 ; String str ; s1 = new Stack<String>(); s1.push( “ humble ” ); s1.push( “ bumble ” ); s1.push( “ mumble ” ); s1.pop();

braden
Download Presentation

Generics

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Generics

  2. Example Stack<E> + Stack<E>() + boolean isEmpty() + void push(E z) + E pop() + E peek() Stack<String> s1, s2; String str; s1 = new Stack<String>(); s1.push( “humble” ); s1.push( “bumble” ); s1.push( “mumble” ); s1.pop(); s1.push( “tumble” ); str = (String) s1.peek(); s1.push( “rumble” ); s1.push( “crumble” ); s1.pop(); s1.pop(); s1.push( s1.peek() ); s2 = new Stack<String> (); while ( !s1.isEmpty() ) { s2.push( s1.peek() ); s1.pop(); }

  3. Generics • A generic class is a class that is parameterized over types. T1 and T2 are type parameters. public class Pair<T1,T2> { private T1 first; private T2 second; public Pair(T1 first, T2 second) { this.first = first; this.second = second; } public T1 getFirst() { return first; } public T2 getSecond() { return second; } public void setFirst(T1 first) { this.first = first; } public void setSecond(T2 second) { this.second = second; } } Type arguments are supplied when the class is used. public class PairDriver { public static void main(String[] args) { Pair<String, Integer> p1 = new Pair<>(“Kenny”, 1); Pair<Integer, Double> p2 = new Pair<>(2, 3.5); String x1 = p1.getFirst(); Integer x2 = p1.getSecond(); Integer x3 = p2.getFirst(); Double x4 = p2.getSecond(); Pair<Pair<String, Integer>,Pair<Integer, Double>> p3 = new Pair<>(p1, p2); ??? x5 = p3.getFirst(); ??? x6 = p3.getSecond(); } }

  4. Comparable & Comparator public interface Comparable<T> { public intcompareTo(T e); } • Java has two commonly used interfaces • Comparable<T> • This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering. • The compareTo method this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. • Comparator<T> • A comparison function, which imposes a total ordering on some collection of objects. • The compare method compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second. public interface Comparator<T> { public int compare(T e1, T e2); }

  5. Interface Shape public interface Shape { public double getArea(); public double getPerimeter(); public double getAspectRatio(); } public abstract class AbstractShapeimplements Shape { protected double width, height; public AbstractShape(double width, double height) { this.width= width; this.height=height; } public double getAspectRatio() { return width / height; } }

  6. Example • Can the AbstractShape class implement the Comparable interface? • We define the natural ordering of shapes by keying on the area. public abstract class AbstractShapeimplementsShape, Comparable<Shape>{ protected double width, height; public AbstractShape(double width, double height) { this.width = width; this.height = height; } public double getAspectRatio() { return width / height; } public intcompareTo(Shape e) { double diff = getArea() – e.getArea(); if(diff < 0) { return -1; } else if(diff > 0) { return 1; } else { return 0; } } }

  7. Why the interface? public AbstractShapegetSmallest(AbstractShape[] shapes) { if(shapes.length == 0) throw new NoSuchElementException(); AbstractShapesmallest = shapes[0]; for(inti=1; i<shapes.length; i++){ if(shapes[i].compareTo(smallest) < 0) { smallest = shapes[i]; } } return smallest; } Could write code like this. It finds the smallest shape in an array of AbstractShapes. public void example() { AbstractShape[] shapes = new AbstractShape[10]; for(inti=0; i<10; i++) { shapes[i] = getRandomShape(); } AbstractShape smallest = getSmallest(shapes); }

  8. Why the interface? public ComparablegetSmallest(Comparable[] items) { if(items.length == 0) throw new NoSuchElementException(); Comparable smallest = items[0]; for(inti=1; i<items.length; i++){ if(items[i].compareTo(smallest) < 0) { smallest = items[i]; } } return smallest; } Better to write code like this. It finds the smallest “thing” in an array of “things”. public void example() { AbstractShape[] shapes = new AbstractShape[10]; for(inti=0; i<10; i++) { shapes[i] = getRandomShape(); } AbstractShape smallest = getSmallest(shapes); }

  9. Generic Methods • Methods can introduce type parameters Generic type parameter String s = randomChoice(“a”, “b”); Double x = randomChoice(1.0, 2.3); Integer y = randomChoice(3,5); Shape u = new Rectangle(10,30); Shape v = new Rectangle(30, 50); Shape t = randomChoice(u, v); public <T> T randomChoice(T x1, T x2) { if(Math.random() < .5) { return x1; } else { return x2; } }

  10. Generic Methods • Can we write a generic method to accept to elements of some type and return the smallest element? public <T> T smallest(T x1, T x2) { if(x1 < x2) { return x1; } else { return x2; } } This doesn’t work since the “<“ operator is not supported on object types. public <T> T smallest(T x1, T x2) { if(x1.compareTo(x2) < 0) { return x1; } else { return x2; } } This doesn’t work since the “compareTo” method is not supported on objects that don’t implement Comparable.

  11. Generic Methods • Can we write a generic method to accept elements of some type and return the smallest element? • Notation to put an upper-bound on a methods generic parameter • TYPENAME extends UPPERBOUND • Examples: • <T extends JPanel> • <T extends Comparable<T>> • <T extends JComponent> public <T extends Comparable<T>> T smallest(T x1, T x2) { if(x1.compareTo(x2) < 0) { return x1; } else { return x2; } } This works since T has an “upper bound” of Comparable<T>. This means that whatever T is, it is a sub-class of Comparable<T>. String x1 = smallest(“a”, “b”); Integer x2 = smallest(15, 3); Double x3 = smallest(2, -18);

  12. Generics and Subtyping • Consider the following example. What are the conformance rules for generic classes? Pair<Object, Object> p1 = new Pair<Object,Object>(“a”, “b”); p1.setFirst(4); // IS THIS VALID? p1.setSecond(“c”); // IS THIS VALID? Pair<String, Integer> p2 = new Pair<String, Integer>(“a”, 3); p2.setFirst(4); // IS THIS VALID? p2.setSecond(“c”); // IS THIS VALID? p1 = p2; // IS THIS VALID? p1.setFirst(4); p1.setSecond(“c”);

  13. Generics and Conformance • Conformance rules • If A is a non-generic super-class of B then objects of type B conform to A • Shape s = new Rectangle(10,30); • Number x = new Double(3.5); • If A is a generic super-class of B, then objects of B type conform to A only if each generic parameter is an exact match. • List<Shape> x = new LinkedList<Rectangle>; • List<Shape> y = new LinkedList<Shape>;

  14. Bounded Type Parameters • When a method declares a parameterized type, the actual parameters must match exactly. public Object pickOne(TwoOfAKind<Object> pair) { if(Math.random() < . 5) { return pair.getFirst(); } else { return pair.getSecond(); } } public class TwoOfAKind<T> { private T first; private T second; public TwoOfAKind (T first, T second) { this.first = first; this.second = second; } public T getFirst() { return first; } public T getSecond() { return second; } public void setFirst(T first) { this.first = first; } public void setSecond(T second) { this.second = second; } } TwoOfAKind<String> p1 = new TwoOfAKind<String>(“a”, “b”); TwoOfAKind<Object> p2 = new TwoOfAKind<Object>(1, ”c”); Object x = pickOne(p1); Object y = pickOne(p2);

  15. Generics and Wildcards • Wildcards allow us to write truly generic functions. • ? denotes ANY TYPE public Object pickOne(TwoOfAKind<?> pair) { if(Math.random() < . 5) { return pair.getFirst(); } else { return pair.getSecond(); } } TwoOfAKind<String> p1 = new TwoOfAKind<String>(“a”, “b”); TwoOfAKind<Object> p2 = new TwoOfAKind<Object>(1, ”c”); Object x = pickOne(p1); Object y = pickOne(p2);

  16. Generics and Wildcards • The wildcard can be constrained. If A is the name of some class then • ? extends A • the ? stands for some class that is either class A or a SUB CLASS OF A • A is an upper-bound public Comparable pickOne(TwoOfAKind<? extends Comparable> pair) { if(Math.random() < . 5) { return pair.getFirst(); } else { return pair.getSecond(); } } TwoOfAKind<String> p1 = new TwoOfAKind<String>(“a”, “b”); TwoOfAKind<Object> p2 = new TwoOfAKind<Object>(1, ”c”); Object x = pickOne(p1); Object y = pickOne(p2);

  17. Generics and Wildcards • The wildcard can be constrained. If A is the name of some class then • ? super A • the ? stands for some class that is either class A OR A SUPER CLASS OF A • A is a lower-bound public Object pickOne(TwoOfAKind<? super Integer> pair) { if(Math.random() < . 5) { return pair.getFirst(); } else { return pair.getSecond(); } } TwoOfAKind<String> p1 = new TwoOfAKind<String>(“a”, “b”); TwoOfAKind<Number> p2 = new TwoOfAKind<Number>(1, 3.5); Object x = pickOne(p1); Object y = pickOne(p2);

  18. Generic Interface Example public interface Function<X,Y> { public Y apply(X x); } The interface describes one function public class Square implements Function<Double, Double> { public Double apply(Double x) { return x * x; } } Each of these non-abstract classes defines that function. public class IsEven implements Function<Integer, Boolean> { public Boolean apply(Integer x) { return x % 2 == 0; } } public class Redness implements Function<Color, Integer> { public Integer apply(Color color) { return color.getRed(); } }

More Related