CSCE 314 Lecture 30
Jump to navigation
Jump to search
« previous | Friday, November 11, 2011 ("11/11/11 11:11:11") | next »
Co/Contravariance
Basically a subclass is safe to cast to a superclass, but a superclass is not safe to cast into a subclass.
Object[] o = new String[]{"1", "2", "3"};
o[0] = new Integer(1); // throws runtime exception
- Covariance (C<T> is covariant wrt T if A <: B implies C<A> <: C<B>) is safe when reading elements from array. Java supports this.
- Contravariance (C<T> is covariant wrt T if A <: B implies C<B> <: C<A>) is safe when writing elements to array, but Java does not support this.
Note: <: means "is a subtype of"
Example
The code below is contravariant on X and covariant on Y:
class Pair<X, Y>
{
private X fst;
private Y snd;
Pair(X a, Y, b)
{
this.fst = a;
this.snd = b;
}
void setFst(X a)
{
this.fst = a;
}
Y getSnd()
{
return this.snd;
}
}
// Usage; assume C <: B <: A
void getAndSet(Pair<B,B> p, B b)
{
p.setFst(b);
B x = p.getSnd();
}
getAndSet(Pair<A, C>, new B()); // this is safe
getAndSet(Pair<C, A>, new B()); // this is NOT safe
Annotated *variance
- + means covariant (disallows writing)
- − means contravariant (disallows reading)
- * means invariant (disallows reading and writing)
Wildcards
public abstract class Shape {
public abstract void drawOn(Canvas c);
}
public class Circle extends Shape {
private int x, y, radius;
public void drawOn(Canvas c) { /* ... */ }
}
public class Line extends Shape {
private int x1, y1, x2, y2;
public void drawOn(Canvas c) { /* ... */ }
}
public class Canvas {
public void draw(List<Shape> shapes) {
for (Shape s : shapes) s.drawOn(this);
}
}
list<Line> ll; ...; canvas.draw(ll); // ERROR!
Reannotate Canvas::draw with draw(List<? extends Shape> shapes) to bound from below.
- <? extends T> bound from below: covariance
- <? super T> bound from above: contravariance
- <?> provides no bounds: bivariance