Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all...

39
Interface vs. Class 9-4-2013

Transcript of Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all...

Page 1: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Interface vs. Class

9-4-2013

Page 2: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Methods common to all classes: toString(), equals(), hashCode()

Interface vs. Class

Comparable Interface: compareTo()

Arrays

Reading assignment:

Effective Java 2

Ch. 3: Items 8, 9, 10, 12

Ch. 4: Items 13, 14, 18, 19

Java Tutorial:

Learning the Java Language trail: arrays, interfaces

HW#1 due today, 9/4/13

Page 3: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Item 7: equals()

- override Object.equals() for “value” classes

Item 8: hashCode()

- always override Object.hashCode() when you override equals()

Item 9: always override toString()

Note:

equals(), hashCode() & toString() are methods in class Object

Page 4: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

public class X {

// assume fields f1 (float), f2 (object), …, fk

public boolean equals(Object o) {

if (o == this) return true;

if (!(o instanceof X))

return false;

X other = (X) o;

return ( (this.f1 == other.f1) &&

( (this.f2).equals(other.f2) &&

… );

} /* use == for primitive fields,

use equals() for objects */

Page 5: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

public class Circle { public boolean equals(Circle c) { // return true if same center point & radius }

public class FilledCircle extends Circle { public boolean equals(FilledCircle fc) { return super.equals(fc) && (this.fillColor).equals(fc.getColor()) ); } } flaw: doesn’t override Object.equals()!!

Page 6: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Object method: public boolean equals(Object o)

Circle method: public boolean equals(Circle c) // overloads equals() method

FilledCircle method: public boolean equals(FilledCircle c) // overloads equals() method

Page 7: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

consider a list of containing a variety of shapes (circles, lines, squares, arrows)

ArrayList shapeList = …. ; /* list of shapes */

FilledCircle fc1 = … ; /* a given circle */

Object aShape;

Search the list for circle fc1: traverse the list with aShape & compare each element to fc1

if (fc1.equals(aShape)) …

starting in the FilledCircle class, look for method w/ signature equals(Object)

FilledCircle Object

Page 8: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

if (fc1.equals(aShape)) starting in the FilledCircle class, look for method w/ signature equals(Object)

FilledCircle Object

public boolean equals(FilledCircle c) doesn’t match FilledCircle

Circle public boolean equals(Circle c)

doesn’t match

Object public boolean equals(Object o)

matches, so this code is executed

but the equals() method in Object tests for equivalence, not equality!

Page 9: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Object method: public boolean equals(Object o)

Circle method: public boolean equals(Object o) // overrides equals() method

FilledCircle method: public boolean equals(Object o) // overrides equals() method

Page 10: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

if (fc1.equals(aShape))

if (fc1.equals(fc2)) …

It’s OK to both overload and override a method, if it makes sense to do so

starting in the FilledCircle class, look for method w/ signature equals(Object) FilledCircle Object

public boolean equals(Object c) matches, so invoke this code FilledCircle

FilledCircle FilledCircle

still matches, because every FilledCircle is an Object, so invoke FilledCircle.equals()

Page 11: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

“equal” objects should have equal hashcodes

“unequal” objects don’t necessarily have different hashcodes (although hash tables will be more efficient if they do)

if you don’t override hashCode in this case then collections will not work properly for your class

Page 12: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

hashCode() must be consistent: i.e. it always returns the same integer whenever it is invoked on the same object

if 2 objects are “equal” according to the equals(Object) method, then they must have the same hashcode: i.e. hashCode() returns the same integer for each of them

if 2 objects are not equal, hashCode() is not required to return different integer hashcodes for them (but it may be more efficient to do so)

Page 13: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Bad idea, why?

public class Circle {

public int hashCode()

{

return 42;

}

}

Page 14: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

1. Start with a nonzero value, say 17

int result = 17;

2. For each “significant” field f in your object, compute a hash value c for it.

How to do this depends on whether the field is a primitive or an object

3. Combine the results

result = 37*result + c;

Page 15: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

/* hashCode for a circle */

public class Circle {

public int hashCode()

{

int result = 17;

result = 37*result +

Float.floatToIntBits(radius);

result = 37* result + center.hashCode();

return result;

}

}

Page 16: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Suppose you are the class designer for a new class T

T has 3 fields: field1 is a primitive type A, field2 is of type B but won’t be used to compare equality, and field3 is an object type C

Let’s suppose that A is float

Page 17: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

public int hashCode()

{

int result = 17;

result = 37*result +

Float.floatToIntBits(field1);

result = 37* result + field3.hashCode();

return result;

}

}

see Effective Java, p. 38 for how to compute hash codes for other primitive values and for arrays

why 37? It’s an odd prime why 17? Arbitrary, but should be relatively prime to 37

Page 18: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

public class X { // assume fields f1 (float), f2 (object), …, fk public int hashCode() { int result = 17; result = 37*result + Float.floatToIntBits(f1); result = 37*result + f2.hashCode(); … result = 37*result + …; // cf. pp 38-39 return result; }

Page 19: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Item 7: equals() - override Object.equals() for “value” classes Item 8: hashCode() - always override Object.hashCode() when you

override equals() Item 9: always override toString() Item 11: consider implementing Comparable

Note:

equals(), hashCode() & toString() are methods in class Object

compareTo() is not a method in class Object; it is a method in the Comparable interface

Page 20: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

What is an Interface?

How does an Interface differ from a Class?

Head First Java 2, Chapter 8, pp. 219 – 226

Java Tutorial, interfaces

Page 21: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

In the java.lang package:

public interface Comparable {

public int compareTo( Object o );

}

How to use an Interface within a Class:

public class Weapon implements Comparable {

/* Must provide code for compareTo */

public int compareTo( Object o ) {

// code for how to compare two weapons

} }

Page 22: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Adventure game:

public interface Moveable {

public void move(double x, double y);

}

public interface Powered extends Moveable {

public String powerSource();

}

public class Weapon implements Comparable, Moveable { /* Must provide code for compareTo */

public int compareTo( Object o ) { … } /* Must provide code for move */

public void move(double toX, double toY ) { … }

Page 23: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

“specification of an interface or protocol for a class (may be implemented in unrelated classes)”

may not contain instance variables or any code, but may contain (static final) constants

when a class states that it implements an interface, it MUST implement ALL methods in the interface

a class can implement more than one interface

all methods in an interface are abstract and public, with or without the modifiers “public” and/or “abstract”

Page 24: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

an interface can be empty, in which case it is a marker for a special property (e.g. Cloneable, Serializable)

an interface can be used to implement “callbacks”

interfaces can extend other interfaces

cannot instantiate an interface

can declare a reference to one

Page 25: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

public interface Comparable {

public int compareTo( Object o );

}

for x, y objects of the same class

x.compareTo(y) < 0 means “x < y”

x.compareTo(y) > 0 means “x > y”

otherwise, “x is neither < nor > y”

recommended that compareTo() is consistent with equals()

if y cannot be cast to the same class as x, then generates a ClassCast Exception

Page 26: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Circle

Date

String

<<interface>>

Comparable

implements

Die

implements

implements

Page 27: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Circle

FilledCircle

Point HAS-A

IS-A

(composition)

(inheritance)

1

Object

IS-A IS-A

<<interface>>

Comparable

implements implements

Page 28: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

public class Student { private String name; private int stdID;

public int compareTo( Object o )

{ Student other = (Student) o; if (this.name < other.name) return -1; if (this.name > other.name) return 1; return 0; }

This doesn’t implement the Comparable interface String is an object – cannot use < or > to compare

severely flawed

Page 29: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

public class Student implements Comparable {

private String name;

private int stdID;

public int compareTo( Object o ) {

Student other = (Student) o;

return ((this.name).compareTo(other.name));

}

} use < & > to compare primitives invoke compareTo() method to compare objects remember to have “implements Comparable” on the class header

Page 30: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

sgn(x.compareTo(y)) == -sgn(y.compareTo(x))

x.compareTo(y) > 0 && y.compareTo(z) > 0 implies x.compareTo(z) > 0

x.compareTo(y) == 0 implies that for all z, sgn(x.compareTo(z)) == sgn(y.compareTo(z))

strongly recommended that

(x.compareTo(y) == 0) == (x.equals(y))

i.e. consistent with equals

Page 31: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

public class X implements Comparable {

// assume fields f1 (float), f2 (object), …, fk

/* version 1: base on primitive field f1 only */

public int compareTo( Object o ) {

X other = (X) o;

if ( (this.f1) < (other.f1) ) return -1;

if ( (this.f1) > (other.f1) ) return 1; return 0; }

Important:

use <,> to compare primitive fields,

use compareTo() for object fields

Page 32: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

public class X implements Comparable {

// assume fields f1 (float), f2 (object), …, fk

/* version 2: base on object field f2 only */

public int compareTo( Object o ) {

X other = (X) o; return ( (this.f2).compareTo(other.f2) ); }

Exercise:

Implement compareTo() for the Student class as follows:

First compare the name field, if < or >, return -1 or +1, respectively

If the name fields are equal, then return the result of comparing the student ID fields

Page 33: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

int[] sides; // reference, currently null

// int sides[]; is also OK

sides = new int[6]; // 6 slots in array

sides = new int[numSides]; // also OK

int[6] sides; // ERROR (int sides[6] also error)

for (int i = 0; i < sides.length; i++)

sides[i] = i + 1;

int[] sides = {1, 2, 3, 4, 5, 6};

Page 34: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

No longer the preferred idiom to iterate over an array:

for (int i = 0; i < a.length; i++)

doSomething( a[i] );

A new feature of Java 1.5 is a concise version of an iterator, the for-each.

Example:

for (Die d : diceArray)

System.out.println(d);

Page 35: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

The preferred idiom for iterating over collections & arrays

Shape[] drawing = { /* initialize with some circles, lines,

triangles, etc. */ };

for (Shape s : drawing) {

System.out.println ( s );

}

int[] sides = {1, 2, 3, 4, 5, 6};

for (int x : sides) {

System.out.println ( x );

}

for (Element e : elements)

doSomething(e);

Page 36: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

provides class methods for sorting & searching in arrays

final int SIZE = 12;

double[ ] weights = new double[ SIZE ];

for (double element : weights)

element = Math.random();

Arrays.sort(weights);

/* note: quicksort is used to sort doubles */

Page 37: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Circle[] hoops = new Circle[3];

for (int i = 0; i < hoops.length; i++)

hoops[i].draw();

There aren’t any actual circles in the array yet

ERROR… why?

Page 38: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Circle[] hoops = new Circle[3];

hoops[0] = new Circle(1.0f, 1, 1);

hoops[1] = new Circle(2.0f, 2, 2);

hoops[2] = new Circle(3.0f, 3, 3);

for (int i = 0; i < hoops.length; i++)

hoops[i].draw(); // draws the 3 circles

Page 39: Interface vs. Class 9-4-2013jsearlem/cs242/fa13/lectures/05.interfaces.pdfMethods common to all classes: toString(), equals(), hashCode() Interface vs. Class Comparable Interface:

Circle[] hoops = {

new Circle(1.0f, 1, 1),

new Circle(2.0f, 2, 2),

new Circle(3.0f, 3, 3)

};

for (Circle c : hoops)

c.draw(); // draws the 3 circles