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