Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Generics OOP 2009 Tirgul #6 What Are Programs For? Human Tools Machine What is a Type? What Are Generics? • Generic abstract over Types • Classes, Interfaces and Methods can be parameterized by Types • Generics provide increased readability and type safety Example: interface Sequence<E> { void add(E element); E first(); … } How Generics Came to Java GJ http://homepages.inf.ed.ac.uk/wadler/gj/ Prof. Philip Wadler, Prof. Martin Odersky, Dr. Gilad Bracha, Dr. Dave Stoutamire Making Java easier to type and easier to type Also: Industry: Norman Cohen (IBM) , Christian Kemper (Borland), Kresten Thorup (Trifork) Compiler: Dr. Neal Gafter, Iris Garcia, Dr. William H. Maddox Researchers: Prof. Mads Torgersen, Prof. Erik Ernst, Peter von der Ahé , Christian Plesner Hansen, Dr. Mirko Viroli , Prof. Atsushi Igarashi Why Generics? Before: Generics Chapter from Effective Java by Joshua Bloch http://www.infoq.com/resource/articles/bloch-effective-java-2e/en/resources/Bloch_Ch05.pdf Why Generics? After: Effective Java by Joshua Bloch Making a Class Generic Sequence before Generics public class Sequence implements Iterable { protected static class Node { Object _elem; Node _next; Node(Object elem) { _elem = elem; _next = null; } } protected Node _head = null; public void add(Object elem) { Node n = new Node(elem); n._next = head; _head = node; } … Sequence with Generics public class Sequence<E> implements Iterable<E> { protected static class Node<T> { T _elem; Node<T> _next; Node(T elem) { _elem = elem; _next = null; } } protected Node<E> _head = null; public void add(E elem) { Node n = new Node<E>(elem); n._next = head; _head = node; } … Making a Class Generic – cont. Sequence before Generics Sequence with Generics … public Iterator iterator() { return new Iterator() { protected Node p = _head; boolean hasNext() { return p != null; } public Object next() { Object e = p._elem; p = p._next; return e; } }; } } … public Iterator<E> iterator() { return new Iterator<E>() { protected Node<E> p = _head; boolean hasNext() { return p != null; } public E next() { E e = p._elem; p = p._next; return e; } }; } } Generic Methods In java.util.Collections: static <T> Set<T> singleton(T object) ... T, given object of type T returns object of type Set<T> Examples: import static java.util.Collections.singleton; Set<Integer> s = singleton(10); Set<String> s = singleton(“hura“); Set<Integer> s = singleton(“oops“); //doesn‘t compile To force the compiler to choose particular T (sometimes it‘s unable to guess): Set<Object> s = Collections.<Object>singleton(10); Generic methods - bounds • Collection<E> has addAll method <T extends E> boolean addAll(Collection<T> c) T s.t. T extends E … • Method that copies second list into first: static <S, T extends S> void copy(List<S> dest, List<T> src) S,T s.t. T extends S … • If we use a parameter just once, it can be replaced by wildcard - ? (equivalent of x s.t. …) boolean addAll(Collection<? extends E> c) static <S> void copy(List<S> dest, List<? extends S> src) Type Inference With generic methods you don’t need to specify the value of the type parameter explicitly as you must when invoking generic constructors. The compiler figures out the value of the type parameters by examining the types of the method arguments. In the case of the program above, the compiler sees that both arguments to union are of type Set<String>, so it knows that the type parameter E must be String. This process is called type inference. Effective Java by Joshua Bloch Type Inference 2 java.util.Collections: static <T> Comparator<T> reverseOrder() Usage: (i) Comparator<String> cmp1 = reverseOrder(); … cmp1.compare(“foo”, “bar”); … (ii) if (reverseOrder().compare(1, 2) > 0) … The compiler guesses the type based on declaration on the left side of the assignment or by parameters to subsequent method calls. Recursive Generic Definitions • Many methods take a list of elements that implement Comparable, in order to sort the list, search within it, calculate its minimum or maximum, etc. • To do any of these every element in the list must be comparable to every other element in the list, in other words, elements of the list must be mutually comparable. // Using a recursive type bound to express mutual comparability public static <T extends Comparable<T>> T max(List<T> list) {...} • The type bound <T extends Comparable<T>> may be read as “for every type T that can be compared to itself” Effective Java by Joshua Bloch Generics – Term Glossary Subsumption Liskov Substitution Principle Object e has type S iff: e has type T T is derived from S Barbara Liskov, Massachusetts Institute of Technology professor, the winner of the 2008 A.M. Turing Award, the most prestigious prize in computer science Types, Inheritance and Intuition Circle-Ellipse Dilemma Does circle have 2 focuses? NO! Design Principles and Design Patterns Robert C. Martin (Uncle Bob) http://www.objectmentor.com Variance • Covariance A generic class C<X> is said to be covariant in the type parameter X when the subtype relation C<R> <: C<S> holds if R <: S. • Contravariance C<X> is said to be contravariant in X when C<R> <: C<S> holds if S <: R. • Invariance C<X> is said to be invariant in X when C<R> <: C<S> holds only when R = S. • Bivariance C<X> is said to be bivariant in X when C<R> <: C<S> for any R and S On Variance-Based Subtyping for Parametric Types Atsushi Igarashi and Mirko Viroli Mathematical Perspective In Java: class … { public Y f(X x) { … } } Y טווח f X תחום In Math: f:XY Example: f: N R g: Z R+ What is the relationship between f and g? Doctor’s Visit class Doctor { … } class Pediatrician extends Doctor { … } class Sexologist extends Doctor { …} class Person { class Person { void see(Doctor dr) … Doctor getDoctor() … } } class Child extends Person { class Child extends Person { @Override void see(Pediatrician dr) … @Override Pediatrician getDoctor() } } Person kid = new Child(); Person kid = new Child(); Doctor dr = kid.getDoctor(); Doctor drRuth = new Sexologist(); kid.see(drRuth); // NO!!! Covariance Example: Java Arrays On Variance-Based Subtyping for Parametric Types Atsushi Igarashi and Mirko Viroli Variance using wildcards • Generics are invariant: for any two distinct types Type1 and Type2, List<Type1> is neither a subtype nor a supertype of List<Type2> • We use wildcards to define co- and contravariance: interface Collection<E> { … void addAll(Collection<? extends E> c); … } class TreeSet<E> { … TreeSet(Comparator<? super E> comparator) { …} } http://www.daimi.au.dk/~madst/tool/literature.html More complex bounds java.util.Collections: static <T> int binarySearch( List<? extends T> list, T key, Comparator<? super T> c) static <T extends Comparable<? super T>> void sort(List<T> list) com.google.common.collect.Iterables: static <F,T> Iterable<T> transform(Iterable<F> fromIterable, Function<? super F,? extends T> function) interface Function<F,T> { T apply(F from); } Links • Generics Tutorial by Gilad Bracha http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf • Angelika Langer Generics FAQ: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html • Java Generics and Collections by Maurice Naftalin, Philip Wadler (in the library) • Effective Java by Josh Bloch http://www.infoq.com/resource/articles/bloch-effective-java2e/en/resources/Bloch_Ch05.pdf