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

Post on 17-Jun-2020

3 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

Transcript

Interface vs. Class

9-4-2013

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

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

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 */

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()!!

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

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

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!

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

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()

“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

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)

Bad idea, why?

public class Circle {

public int hashCode()

{

return 42;

}

}

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;

/* 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;

}

}

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

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

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; }

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

What is an Interface?

How does an Interface differ from a Class?

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

Java Tutorial, interfaces

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

} }

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 ) { … }

“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”

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

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

Circle

Date

String

<<interface>>

Comparable

implements

Die

implements

implements

Circle

FilledCircle

Point HAS-A

IS-A

(composition)

(inheritance)

1

Object

IS-A IS-A

<<interface>>

Comparable

implements implements

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

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

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

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

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

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};

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);

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);

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 */

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?

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

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

top related