Equals, Typechecking, and ExceptionsPrinciples of Software System ConstructionPrinciples of Software System ConstructionJonathan Aldrich Bill ScherlisSpring 2012Implementing equals()• Recall: identity vs. equality in Java– a == b is identity—are the references the same?– a.equals(b) is equality—do the objects represent an equivalent value?• The default equals() implementation– Defined in class Object– public boolean equals(Object obj) { return (this == obj); }•Thus, override equals() when logical equality for a class differs from object identity•object identity• Mathematical properties of an equivalence relation– Reflexive: ∀x x.equals(x)– Symmetric: ∀x,y x.equals(y) ⇔ y.equals(x)– Transitive: ∀x,y,z x.equals(y) ∧ y.equals(z) ⇒ x.equals(z)• Additional requirements of equals()– Consistent: invoking x.equals(y) multiple times yields a consistent answer, unless an object pointed to by x or y is modified.– ∀x x.equals(null) is falseFall 2011 15-214: Course Introduction 2equals(): a first attemptclass Object {public boolean equals(Object obj) { return (this == obj); }// other methods…}class Vertex {class Vertex {private String name;@Overridepublic boolean equals(Vertex vert) {return this.name == vert.name;}}Fall 2011 15-214: Course Introduction 3Now let’s have some funclass Object {public boolean equals(Object obj) {return (this == obj);}// other methods…}class Vertex {// what does this print?Vertex v1 = new Vertex(“JohnDoe”);Vertex v2 = new Vertex(“John” + “Doe”);Vertex v3 = null;Object o = new Vertex(“JohnDoe”);System.out.println(v1.equals(v2));System.out.println(o.equals(v1));System.out.println(v1.equals(v3));class Vertex {private String name;@Overridepublic boolean equals(Vertex vert) {return this.name == vert.name;}}System.out.println(v1.equals(v3));Fall 2011 15-214: Course Introduction 4Many problems:• Does not override Object.equals()• Compares strings for identity, not equality• Does not consider a null VertexHow do we fix it?class Object {public boolean equals(Object obj) {return (this == obj);}// other methods…}class Vertex {class Vertex {private String name;@Overridepublic boolean equals(Vertex vert) {return this.name == vert.name;}}Fall 2011 15-214: Course Introduction 5Many problems:• Does not override Object.equals()• Compares strings for identity, not equality• Does not consider a null VertexA better versionclass Object {public boolean equals(Object obj) {return (this == obj);}// other methods…}class Vertex {private String name;// what does this print?Vertex v1 = new Vertex(“JohnDoe”);Vertex v2 = new Vertex(“John” + “Doe”);Vertex v3 = null;Object o = new Vertex(“JohnDoe”);System.out.println(v1.equals(v2));System.out.println(o.equals(v1));System.out.println(v1.equals(v3));private String name;@Overridepublic boolean equals(Object obj) {if (!(obj instanceof Vertex))return false;Vertex vert = (Vertex) obj;return name.equals(vert.name);}}Fall 2011 15-214: Course Introduction 6More fun with equals()public class Point {private final int x;private final int y;public Point(int x, int y) {this.x = x;this.y = y;}@Overridepublic class ColorPoint extends Point {private final Color color;public ColorPoint(int x, int y, Color c) {super(x,y);color = c;}@Overridepublic booleanequals(Object obj) {@Overridepublic boolean equals(Object obj) {if (!(obj instanceof Point))return false;Point p = (Point) obj;return x == p.x && y == p.y;}}public booleanequals(Object obj) {if (!(obj instanceof ColorPoint))return false;ColorPoint cp= (ColorPoint) obj;return super.equals(cp)&& color.equals(cp.color);}}Fall 2011 15-214: Course Introduction 7// client codePoint p = new Point(1, 2);ColorPoint cp = new ColorPoint(1, 2, Color.BLUE);System.out.println(p.equals(cp) + “ should be equivalent to “ + cp.equals(p));Even more fun with equals()!public class Point {private final int x;private final int y;public Point(int x, int y) {this.x = x;this.y = y;}@Overridepublic class ColorPoint extends Point {private final Color color;public ColorPoint(int x, int y, …@Overridepublic boolean equals(Object obj) {if (!(obj instanceof Point))return false;@Overridepublic boolean equals(Object obj) {if (!(obj instanceof Point))return false;Point p = (Point) obj;return x == p.x && y == p.y;}}return false;if (!(obj instanceof ColorPoint)return obj.equals(this);ColorPoint cp= (ColorPoint) obj;return super.equals(cp)&& color.equals(cp.color);}}Fall 2011 15-214: Course Introduction 8// client codePoint p = new Point(1, 2);ColorPoint blueCP = new ColorPoint(1, 2, Color.BLUE);ColorPoint redCP = new ColorPoint(1, 2, Color.RED);// now try all the combinations…is it transitive?An Abstract Class Solutionpublic abstract class Point {private final int x;private final int y;public Point(int x, int y) {this.x = x;this.y = y;}@Overridepublic booleanequals(Object obj) {public class ColorPoint extends Point {private final Color color;public ColorPoint(int x, int y, …@Overridepublic boolean equals(Object obj) {if (!(obj instanceof ColorPoint)return false;ColorPointcp= (ColorPoint) obj;Point p = (Point) obj;return x == p.x && y == p.y;}}public class PointImpl extends Point {public PointImpl(int x, int y) { super(x,y); }@Overridepublic boolean equals(Object obj) {if (!(obj instanceof PointImpl))return false;return super.equals(obj);}}return super.equals(cp)&& color.equals(cp.color);}}Fall 2011 15-214: Course Introduction 9Moral: don’t extend a concrete class!• It’s almost impossible to obey the equals() contract• Often leads to other design problemsChallenge (hard)• Write a concrete Point class that does not reference ColorPoint• Show how Point can be extended with a ColorPoint subclass• Show that your implementation of equals() obeys the contract• Hint: the solution is a bit of a hack, and requires techniques we have not discussed yet in this classFall 2011 15-214: Course Introduction 10Typechecking Overview• Scanning a program to determine whether the operations being invoked are applicable to the types they are invoked on• Benefits– Finds errors earlyinth = “hi” / “2”;inth = “hi” / “2”;– Compiles code more efficientlyfoo.bar(); // can jump straight to bar() code// rather than search for an implementation of bar– Automatically checked program documentationvoid baz(frob) { /* what am I supposed to do with a frob? */ }void baz(Car frob) { /* oh, look, I can drive it! */ }Fall 2011 15-214:
View Full Document