Download Generics

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
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:XY
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