Upload
others
View
6
Download
0
Embed Size (px)
Citation preview
toad
Fall 2012
© 2012 C Garrod, J Aldrich, and W Scherlis
School of Computer Science
Principles of Software Construction: Objects, Design and Concurrency Contracts, equality, and type polymorphism
Jonathan Aldrich Charlie Garrod
15-214
toad 2 15-‐214 Garrod
Administrivia
• Homework 1 due tonight § But you may use late days…
• Homework 2 coming soon § A virtual world § Part 1 due next Thursday § Part 2 due the following Tuesday
toad 3 15-‐214 Garrod
Key concepts from Tuesday
• Polymorphism § Method dispatch
• Types and typechecking
toad 4 15-‐214 Garrod
Key concepts for today
• The java.lang.Object contracts
• A lesson in equality
• Java scopes § Variable shadowing
• Type polymorphism § Java Generics
toad 5 15-‐214 Garrod
Recall: The java.lang.Object!
• All Java objects inherit from java.lang.Object!
• Commonly-used/overridden public methods: § String !toString()!§ boolean !equals(Object obj)!§ int !hashCode()!§ Object !clone()!
toad 6 15-‐214 Garrod
The .equals(Object obj) contract
• An equivalence relation § Reflexive: ∀x ! x.equals(x)!§ Symmetric: ∀x,y! x.equals(y) if and only if y.equals(x)!§ Transitive: ∀x,y,z x.equals(y) and y.equals(z) implies x.equals(z)!
• Consistent § Invoking x.equals(y) repeatedly returns the same value unless x or y is modified
• x.equals(null) is always false
toad 7 15-‐214 Garrod
The .hashCode() contract
• Consistent § Invoking x.hashCode() repeatedly returns same value unless x is modified
• Equality implies hashCode() equality § i.e., x.equals(y) implies x.hashCode() == y.hashCode()!§ The reverse implication is not necessarily true:
• x.hashCode() == y.hashCode() does not imply x.equals(y)!
• Advice: You should override .equals() if and only if you override .hashCode()!
toad 8 15-‐214 Garrod
The .clone() contract
• Returns a deep copy of an object
• Generally (but not necessarily!): § x.clone() != x § x.clone().equals(x)!
toad 9 15-‐214 Garrod
A lesson in equality
Implement the .equals method for the Point class.
public class Point {! private final int x;! private final int y;! public Point(int x, int y) {! this.x = x;! this.y = y;! }!}!
toad 10 15-‐214 Garrod
A tempting but incorrect solution
public class Point {! private final int x;! private final int y;! public Point(int x, int y) {! this.x = x;! this.y = y;! }!}!
public boolean equals(Point p) {! return x == p.x && y == p.y;! }!
toad 11 15-‐214 Garrod
A tempting but incorrect solution
boolean equals(Point p) does not override boolean equals(Object obj)!
public class Point {! private final int x;! private final int y;! public Point(int x, int y) {! this.x = x;! this.y = y;! }!}!
public boolean equals(Point p) {! return x == p.x && y == p.y;! }!
Types must match
toad 12 15-‐214 Garrod
A correct solution
public class Point {! private final int x;! private final int y;! public Point(int x, int y) {! this.x = x;! this.y = y;! }!! public boolean equals(Object obj) {! if (!(obj instanceof Point) ! return false;! Point p = (Point) obj;! return x == p.x && y == p.y;!}!
toad 13 15-‐214 Garrod
A new challenge
Implement .equals for the ColorPoint class. You may assume Color correctly implements .equals!
public class Point {! private final int x;! private final int y;! public Point(int x, int y) {! this.x = x;! this.y = y;! }!! public boolean equals(Object obj) {! if (!(obj instanceof Point) ! return false;! Point p = (Point) obj;! return x == p.x && y == p.y;!}!
public class ColorPoint! extends Point {! private final Color color;!! public ColorPoint(int x, ! int y,! Color color) {! super(x, y);! this.color = color;! }!}!
toad 14 15-‐214 Garrod
A tempting solution
public class Point {! private final int x;! private final int y;! public Point(int x, int y) {! this.x = x;! this.y = y;! }!! public boolean equals(Object obj) {! if (!(obj instanceof Point) ! return false;! Point p = (Point) obj;! return x == p.x && y == p.y;!}!
public class ColorPoint! extends Point {! private final Color color;!! public ColorPoint(int x, ! int y,! Color color) {! super(x, y);! this.color = color;! }!! public boolean equals(Object obj) {! if (!(obj instanceof ColorPoint))! return false;! ColorPoint cp = (ColorPoint) obj;! return super.equals(cp) &&! color.equals(cp.color);!}!
toad 15 15-‐214 Garrod
A tempting solution
A problem: p.equals(cp)!but !cp.equals(p):
public class Point {! private final int x;! private final int y;! public Point(int x, int y) {! this.x = x;! this.y = y;! }!! public boolean equals(Object obj) {! if (!(obj instanceof Point) ! return false;! Point p = (Point) obj;! return x == p.x && y == p.y;!}!
public class ColorPoint! extends Point {! private final Color color;!! public ColorPoint(int x, ! int y,! Color color) {! super(x, y);! this.color = color;! }!! public boolean equals(Object obj) {! if (!(obj instanceof ColorPoint))! return false;! ColorPoint cp = (ColorPoint) obj;! return super.equals(cp) &&! color.equals(cp.color);!}!
Point p = new Point(2, 42);!ColorPoint cp = new ColorPoint(2, 42, Color.BLUE);!
toad 16 15-‐214 Garrod
More problems
Consider:!
public class Point {! private final int x;! private final int y;! public Point(int x, int y) {! this.x = x;! this.y = y;! }!! public boolean equals(Object obj) {! if (!(obj instanceof Point) ! return false;! Point p = (Point) obj;! return x == p.x && y == p.y;!}!
public class ColorPoint! extends Point {! private final Color color;!! public ColorPoint(int x, ! int y,! Color color) {! super(x, y);! this.color = color;! }!! public boolean equals(Object obj) {! if (!(obj instanceof Point))! return false;! if (!(obj instanceof ColorPoint))! return super.equals(obj);! ColorPoint cp = (ColorPoint) obj;! return super.equals(cp) &&! color.equals(cp.color);!}!
Point p = new Point(2, 42);!ColorPoint cp1 = new ColorPoint(2, 42, Color.BLUE);!ColorPoint cp2 = new ColorPoint(2, 42, Color.MAUVE);!
toad 17 15-‐214 Garrod
An abstract solution
public abstract class Point {! private final int x;! private final int y;! public Point(int x, int y) {! this.x = x;! this.y = y;! }!! public boolean equals(Object obj) {! if (!(obj instanceof Point) ! return false;! Point p = (Point) obj;! return x == p.x && y == p.y;!}!
public class ColorPoint! extends Point {! private final Color color;!! public ColorPoint(int x, ! int y,! Color color) {! super(x, y);! this.color = color;! }!! public boolean equals(Object obj) {! if (!(obj instanceof ColorPoint))! return false;! ColorPoint cp = (ColorPoint) obj;! return super.equals(cp) &&! color.equals(cp.color);!}!
public class PointImpl extends Point {! public PointImpl(int x, int y) { super(x,y); }! public boolean equals(Object obj) {! if (!(obj instanceof PointImpl))! return false;! return super.equals(obj);! }!
toad 18 15-‐214 Garrod
Key concepts for today
• The java.lang.Object contracts
• A lesson in equality
• Java scopes § Variable shadowing
• Type polymorphism § Java Generics
toad 19 15-‐214 Garrod
Variable shadowing in Java
• Variable shadowing: when a name within some program inner scope matches a name in some outer scope § e.g., !public class Dog {!
! ! String name;! public Dog (String name) {! this.name = name;! ! }! }!
• Java has class variables, instance variables, and local variables § Local variables may shadow instance or class variables § A subclass’s variables may shadow superclass variables
toad 20 15-‐214 Garrod
Inner scopes in Java
• Curly braces define a new scope § e.g., public void printAsInt(String s) {!
! try {! ! ! Integer x = Integer.valueOf(s);!! !} catch (NumberFormatException e) {!! ! // we ignore the exception!! !}!! !System.out.println(x); // x is undefined!! }! ! ! ! !// in this scope!! !
toad 21 15-‐214 Garrod
Inner classes in Java
• Classes can be defined inside other classes, or even inside class methods § e.g., A LinkedList.Node class accessible only from within a LinkedList class: ! public class LinkedList {!! private static class Node {!
public int val;! public Node next;! public Node(int v, Node n) {! val = v; ! next = n;! }! }! Node head;! // …! }!
toad 22 15-‐214 Garrod
Key concepts for today
• The java.lang.Object contracts
• A lesson in equality
• Java scopes § Variable shadowing
• Type polymorphism § Java Generics
toad 23 15-‐214 Garrod
Recall the JavaCollection API (excerpt)
Collection
List Set AbstractCollection
AbstractList
LinkedList
Vector
HashSet
AbstractSequentialList
AbstractSet
Cloneable
ArrayList
interfaces
toad 24 15-‐214 Garrod
Consider the java.util.Stack!
public class Stack {!
public void push(Object obj) { … }!
public Object pop() { …}!
}
• Some possible client code?: Stack stack = new Stack();!String s = “Hello!”;!stack.push(s);!String t = stack.pop();!
toad 25 15-‐214 Garrod
Consider the java.util.Stack!
public class Stack {!
public void push(Object obj) { … }!
public Object pop() { …}!
}
• Some possible client code: Stack stack = new Stack();!String s = “Hello!”;!stack.push(s);!String t = (String) stack.pop();!
To fix the type error
toad 26 15-‐214 Garrod
Type polymorphism via Java Generics
• The java.util.Stack instead § A stack of some type T: public class Stack<T> {! public void push(T obj) { … }! public T pop() { … }! }!
• Improves typechecking, simplifies(?) client code: Stack<String> stack = new Stack<String>();!String s = “Hello!”;!stack.push(s);!String t = stack.pop();!!
toad 27 15-‐214 Garrod
Next week
• Formal techniques for program correctness § Proving and using invariants § Static correctness provers