Transcript interface
Interfaces,
and Polymorphism
Sections 8.4, 8.1
Outcomes
Create
a polymorphic function for Lists
and other interfaces
Recognize,
write, and implement interfaces
Make a class sortable by implementing the
Comparable<> interface
BONUS: Add different ways of sorting by
implementing the Comparator<> interface
Similar Classes
Separate
classes can have similar actions
ArrayList & LinkedList
» add an item, remove an item, ask if empty, get an
item from a given position, …
But
they are completely different data types
can’t use an ArrayList method on a LinkedList
but the LinkedList version of that method
would have exactly the same code in the body
ArrayList vs. LinkedList
p.v. printArrayList(
ArrayList<String> l) {
Sopln(“List is:”);
for (String s : l) {
Sopln(“\t” + s);
}
Sopln();
}
Only
p.v. printLinkedList(
LinkedList<String> l) {
Sopln(“List is:”);
for (String s : l) {
Sopln(“\t” + s);
}
Sopln();
}
difference is “Array” “Linked”
and that’s only in the header!
the bodies are exactly the same
See SillyDuplication.java
Calling AL/LL Methods
Arguments
must match parameters
ArrayList<String> al = new ArrayList<String>();
LinkedList<String> ll = new LinkedList<String>();
…
printArrayList(al);
// OK
printLinkedList(ll);
// OK
printArrayList(ll);
// NOT OK
printLinkedList(al);
// NOT OK
errors:
» required ArrayList, found LinkedList
» required LinkedList, found ArrayList
“List” Actions
ArrayList
& LinkedList have same methods
add(_), remove(_), isEmpty(), get(_), …
also listIterator()
All
these methods are “List” actions
things we want to do with a list
It’d
be nice if we could write one method to
deal with both kinds of lists
turns out we can!
Polymorphic printList Method
One
method that works for both types
public void printList(List<String> l) {
System.out.println(“List is:”);
for (String s : l) {
System.out.println(“\t” + s);
}
System.out.println();
}
called “polymorphic” (= many shapes)
Works
because Java knows what Lists do
See ListsAreLists.java
Calling List Methods
Both
kinds match List parameters
ArrayList<String> al = new ArrayList<String>();
LinkedList<String> ll = new LinkedList<String>();
…
printList(al);
// OK
printList(ll);
// OK
no errors!
» printList is expecting to be given a List
» ArrayLists are Lists
» LinkedLists are Lists
Polymorphic Variables
Parameters
are variables
we can have List variables other places, too
List<String> al = new ArrayList<String>();
List<String> ll = new LinkedList<String>();
…
printList(al);
// OK
printList(ll);
// OK
But!
No such thing as a List object
List<String> al = new List<String>();
java.util.list is abstract; cannot be instantiated
What is java.util.List
It’s
what’s called an interface
a list of public methods without bodies
It’s
a list of things an object could do
but doesn’t say how it would do them
Every
List has certain methods defined
add(_), remove(_), get(_), listIterator(), …
but each kind of List does them its own way
» ArrayList one way; LinkedList another way
google java List to see what methods a List must have
Why Use Interfaces?
We
can say what needs doing without
saying how it needs to be done
because we mostly don’t care how it’s done
(e.g.) we need a class we can use as a list
» this class says it can be used as a list, so let’s use it
don’t get stuck with one class
» make an interface & let anyone implement it
» use new & better classes as they come along
• (it’s much easier to add new things)
See StringList.java and StringListDemo.java
Interface Declaration
public interface InterfaceName {
Public_Constant_Declarations…
Public_Method_Headers…
}
Very
much like a class definition
interface instead of class
methods all public
» none of them have bodies!
public constants allowed, too
Interface
Tell
Java that group of actions goes together
name the group of actions
say what the actions are
do not say how to do them
» different kinds of things may do them different ways
public interface Measurable {
public double getArea();
public double getPerimeter();
}
See Measurable.java
Using an Interface
Tell
method to expect a Measurable object
can use any Measurable method for that object
» getArea or getPerimeter
public double roundness(Measurable m) {
return 4 * Math.PI
* m.getArea()
/ Math.pow(m.getPerimeter(), 2);
}
cannot use any other methods! (*)
» we don’t know what other methods it might have
(*) not exactly true, but pretty close!
See MeasuringStuff.java
Using Measurable Objects
Suppose
Circle is Measurable
Circle c = new Circle(10.0);
System.out.println(“Roundness of c is ” + roundness(c));
c has getArea and getPerimeter methods…
» because Circles are Measurables
…so method works just fine
similarly for Rectangles
Rectangle r = new Rectangle(10.0, 20.0);
System.out.println(“Roundness of r is ” + roundness(r));
Roundness of c is 1.0
Roundness of r is 0.6981317007977318
Exercise
Declare
an interface named Playable that
has the following methods:
void play()
void play(int numTimes)
double playLength()
Making Classes Measurable
Need
to know that a class is Measurable
it’s not enuf to just have the methods
need to tell Java that we have the methods
Done
in the class declaration
an implements clause (compare: throws clause)
public class Circle implements Measurable { … }
public class Rectangle implements Measurable { … }
tells Java they have getArea & getPerimeter
» don’t lie! Java will catch you out
The Circle Implementation
public class Circle implements Measurable {
private double radius;
public Circle(double r)
{ radius = r; }
public double getRadius()
{ return radius; }
public double getCircumference()
{ return 2 * Math.PI * radius; }
public double getDiameter()
{ return 2 * radius; }
public double getArea() { return Math.PI * Math.pow(radius, 2); }
public double getPerimeter ()
{ return getCircumference(); }
}
says it implements Measurable, then does
» has other methods, too – but that’s OK
See Circle.java
The @Override Annotation
NetBeans
will notice methods that
implement the Measurable interface
will ask you to add @Override annotation
Please do so!
@Override
public double getArea()
@Override
public double getPerimeter ()
{ return Math.PI * Math.pow(radius, 2); }
{ return getCircumference(); }
» NOTE: only on the methods named in Measurable
public double getDiameter()
{ return 2 * radius; }
Overriding Interface Methods
Interface
says that class has the method
does not say how the method works
Class
says how the method works
@Override says that this method is the same as
the one from the interface
» so computer can tell if you said it wrong
The two must match exactly
public double getArea();
// from Measurable
public double getArea() { … } // from Circle
Actually, the parameter names can be different….
The Rectangle Implementation
public class Rectangle implements Measurable {
private double length, width;
public Rectangle(double l, double w)
{ length = l; width = w; }
public double getLength()
{ return length; }
public double getWidth()
{ return width; }
@Override
public double getArea()
{ return length * width; }
@Override
public double getPerimeter ()
{ return 2 * (length + width); }
}
says it implements Measurable, then does
» the implementations are different than for Circles
See Rectangle.java
Exercise
Write
a Square class that implements the
Measurable interface
it has an edgeLength (double)
area is edgeLength squared
perimeter is four times edgeLength
Non-Interface Methods
Class
may have methods that are not part of
the interface
Rectangle: getHeight & getWidth
Circle: getRadius & getCircumference
Polymorphic
parameters/variables cannot
use those methods
can only use interface methods
What’s OK?
Methods
you can ask for depend on the
variable, not the object
Circle c = new Circle(10);
c.getPerimeter();
c.getArea();
c.getRadius();
c.getCircumference();
Rectangle r = new Rectangle(10, 20);
r.getPerimeter();
r.getArea();
r.getHeight();
r.getWidth();
Measurable m = new Circle(10);
m.getPerimeter();
m.getRadius();
m.getArea();
m.getCircumference();
Compile-Time Method Checking
Try
to make sure program won’t crash
make it as safe as we can (no guarantees!)
Asking
a Rectangle for its radius would
cause a crash
Measurable could be a Rectangle
Asking a Measurable for its radius could
cause a crash
Run-Time Method Selection
Anything
we ask a Measurable to do...
...will be part of the interface
because our compile-time checking made sure
The
Measurable object knows how to do it
because of compile-time checking of class
Object
uses its own version of the method
known as late (or dynamic) binding
In C++, early (static) binding chooses a
version of the method at compile time.
Variables & Types
Measurable
variable is polymorphic
can hold a Circle or Rectangle object
can assign from a different type variable
Measurable m;
Circle c = new Circle(10);
Rectangle r = new Rectangle(10, 20);
m = c;
m = r;
Compare storing an int variable
into a double variable:
int n = 5;
double x = n;
Variables & Types
Cannot go the other way around
Measurable m = new Circle(10);
Rectangle r;
Circle c;
r = m;
c = m;
doesn’t like either of those
Compare storing a double
variable into an int variable:
double x = 5.0;
int n = x;
Type Casting
Can
tell Java you want to do it anyway!
tell Java to treat the Measurable as a Circle
Measurable m = new Circle(10);
Circle c;
c = (Circle) m;
will crash if object is wrong type
Rectangle r;
r = (Rectangle) m;
Crash
Contrast casting a double
variable into an int variable:
double x = 5.5;
int n = (int)x;
Checking the Type
Can
ask if an object is a given type
hey, m, are you are Circle?
if (m instanceof Circle) {
Note: all lower-case letters!
Circle c = (Circle) m;
double radius = c.getRadius();
Still can’t ask m to do non-Measurable
if (m instanceof Circle)
System.out.print(m.getRadius());
stuff
Exercise
Check
a Measurable variable to see if it
holds a Rectangle object.
if it does, print out the Rectangle’s length and
width
Implementing Multiple Interfaces
Can
implement more than one interface
list interfaces, separated by commas
public class MultiPurpose implements InterA, InterB {...}
public class Yikes implements IA, IB, IC, IDa, IDb {...}
Must
define every method from every
interface it implements
no lying!
Extending Interfaces
Consider this interface:
public interface Polygonal {
public double getArea();
public double getPerimeter();
public int getNumberOfSides();
}
has all Measurable’s methods, plus one more
Can simplify the definition:
public interface Polygonal extends Measurable {
public int getNumberOfSides();
}
See Polygonal.java
Implementing Polygonal
Anything
that implements Polygonal must
define all the methods mentioned in
Polygonal interface...
public int getNumberOfSides()
...plus all those mentioned
public double getArea()
public double getPerimeter()
in Measurable
And So On...
Can
extend an interface that extends another
just adding more methods to implement
public interface RegularPolygonal extends Polygonal {...}
Can
extend more than one interface
again, adding more methods to implement
public interface FiniteSurface
Measurable
extends Measurable,
Colourable
Colourable {
Polygonal
...
FiniteSurface
}
RegularPolygonal
See them!
Combining Interfaces
When
one interface extends two others...
(or more than two others)
...it
may not need any more methods
it just puts those two (or more) interfaces
together
use empty braces (no new methods required)
public interface FiniteSurface
extends Measureable, Colourable {}
Exercise
What methods must these classes implement?
public interface IA {public void is();}
public interface IB {public int howMany();}
public interface IC extends IB {public String whatKind();}
public interface ID extends IA, IC {}
public interface IE extends IA, IB {public void what();}
public class A implements IE {...}
public class B implements ID {...}
public class C implements IA, IB {...}
Interface Summary
An
interface is a data type
variables can have that data type
» including (especially) parameters for methods
such variables (methods) called polymorphic
An
interface lists public methods
each implementing class implements them
each class has its own implementation
these classes are similar kinds of things
» Circles and Rectangles are similar kinds of things
The Comparable<…> Interface
Collections.sort
sorts Lists of some types
Java must know how to sort them
knows how to sort Integer, Double, String, …
doesn’t know how to sort user-defined classes
Tell
Java how to sort user-defined classes
implement the Comparable<…> interface
Collections.sort expects to be given a
List<Comparable<…>>
The Comparable<…> Interface
Have
to fill in the <…>
what kind of thing it can be sorted with
almost always itself
public class Student implements Comparable<Student>
Has
exactly one method
compareTo says how to compare to other
public int compareTo(Student other)
» how does this Student compare to other Student
» for Professor: public int compareTo(Professor other)
Sorting Students
Let’s
sort Students by name
name is a String
String has a compareTo method
so just return whatever it returns
public int compareTo(Student other) {
return this.name.compareTo(other.name);
}
“if you want to compare Students, compare
their names.”
See byName/Student.java
Sorting Students
Add Students to list; sort list; print
List<Student> ss = new ArrayList<>();
ss.add(new Student(“Jake”));
ss.add(new Student(“Angie”));
ss.add(new Student(“Geety”));
Collections.sort(ss);
System.out.println(ss);
list
[Angie (A00000002), Geety (A00000003), Jake (A00000001)]
See byName/SortStudents.java
Sorting by Grade
Sorting
by numbers uses subtraction
smallest to largest: this.number – other.number
largest to smallest: other.number – this.number
but result must be an int!
public int compareTo(Student other) {
return other.getAverage() – this.getAverage();
}
sorts Students from highest to lowest grade
See byGrade/Student.java and byGrade/SortStudents.java
Sorting by Double Values
Need
to change double to int
(int) no good – changes 0.5 to 0 instead of 1
Use
Math.signum to get sign of result
then change to int
public int compareTo(Line other) {
double result = this.length – other.length;
double sign = Math.signum(result); // -1.0, 0.0, or +1.0
return (int)sign;
}
» sorts from shortest to longest
See Line.java and SortLines.java
Exercise
Write
a compareTo method that sorts
Students by A_NUMBER
remember, it’s a String
Write
a compareTo method that sorts Lines
from longest to shortest
each Line has a length
Questions?
(Bonus
material follows)
having multiple sorting methods for one class
the Comparator<…> interface
anonymous classes
Sorting in Many Ways
Sometimes
want to sort by name, other
times by grade (and other times by A#)
Collections.sort accepts a second argument
it’s a “way to sort”
» Collections.sort(words, String.CASE_INSENSITIVE_ORDER);
we’ll want (at least) these “ways to sort”:
» Student.BY_NAME
» Student.BY_GRADE
» Student.BY_ANUMBER
The Comparator<…> Interface
The
interface for “ways to sort”
Need a class to implement the interface
so we need three classes
public class SortStudentsByName
implements Comparator<Student> { … }
public class SortStudentsByGrade
implements Comparator<Student> { … }
public class SortStudentsByANumber
implements Comparator<Student> { … }
See the folder comparators/withClasses in this week’s sample code
The Comparator<…> Interface
The
interface for “ways to sort”
has exactly one method: int compare(_, _)
very similar to compareTo method
public class SortStudentsByName
implements Comparator<Student> {
public int compare(Student one, Student other) {
return one.getName().compareTo(other.getName());
}
}
Student Comparators
Each
comparator in Student is a Comparator
each one is an object of the corresponding class
public static final Comparator<Student> BY_NAME
= new SortStudentsByName();
public static final Comparator<Student> BY_GRADE
= new SortStudentsByGrade();
public static final Comparator<Student> BY_ANUMBER
= new SortStudentsByANumber();
See comparators/withClasses/Student.java
All Those Extra Classes?
Don’t
actually need to create new files
don’t need SortStudentsByName.java &c.
Use
“anonymous” classes instead
put Comparator definition inside Student.java
public static final Comparator<Student> BY_NAME
= new Comparator<Student>() {
public int compare(Student one, Student other) {
return one.getName().compareTo(other.getName());
}
};
See the folder comparators/anonymous in this week’s sample code
Anonymous Classes
Class
without a name
can use it to implement any interface
just need to give the definitions
SomeInterface blah = new SomeInterface() {
// define all interface methods in here!
};
only makes sense for some interfaces
» nothing that needs its own instance variables
» Comparator makes sense; Comparable doesn’t
Questions
Next
week: review on Tuesday
2nd midterm test on Thursday
on weeks 5, 6 and 7
usual rules apply