OverviewFirst, consider the methods we'd want to implement for such a class. At minimum, we'd want a method to add a new element to the list and a method to remove an element from the list. The add method would take as input a new element and would insert it into the correct position in the list, likely maintained as an array. For example, given the list of ints [1, 2, 4, 5], the add method would insert the new element 3 between 2 and 4. Similarly, given the list of Strings ["and", "boy", "dog"], the add method would insert the new element "cat" between "boy" and "dog". Now, consider the algorithm we'd use for the add method. It turns out that the same algorithm will work in both cases:
i = index of last element in list
It would be great if we could implement this algorithm once and reuse it for any type of item we'd like to sort. However, that requires that we think carefully about the type we use for the array that stores the sorted elements. Clearly, we can't use int or String. But, we must be sufficiently specific since not all objects can be compared to other objects, and we must be able to compare the objects in our list to determine their order. What Java allows us to do is specify an interface that defines the methods an object must support. A class that implements that interface must implement the methods defined in the interface, but may do so in any way. Therefore, our list can contain any object that is Comparable , though the objects may be compared in different ways. Interfaces
Essentially, the interface defines the behavior a class must support, and many classes may implement the same interface (that is, support the same function in different ways). You might consider an interface Drivable that defined an abstract method drive . A class Car might implement Drivable, as might a class Bicycle. Defining an Interface
public interface Viewable {
An interface (as shown above) looks very similar to a class.
Implementing an Interface To implement an interface, a class must specify that implements that interface and it must also provide implementations for all of the methods defined in the interface. If a class fails to implement one or more abstract methods from the interface, the compiler will complain.
public class Name implements Viewable {
A class may also implement multiple interfaces.
public class C implements X, Y {
Using Classes that Implement Interfaces Because an interface does not provide implementation for its methods, it cannot be instantiated. The following piece of code would result a compiler error:
Viewable v = new Viewable();
However, the following code is perfectly valid:
Viewable v = new Name("Jane", "Wu");
We describe Name as having an "is-a" relationship with Viewable, as in "a Name is a Viewable". Therefore, a variable that can refer to a Viewable can refer to a Name or an object of any other class that implements Viewable. Similarly, on a Viewable variable, you can invoke any method defined in Viewable. Casting
Now, suppose you wanted to invoke the
setFirst
method on
the variable v defined above. You might try
Viewable v = new Name("Jane", "Wu"); //valid
In order to invoke the method setFirst on the variable v, we must use
casting. Recall that casting tells the compiler to treat one type of variable
as another type.
Viewable v = new Name("Jane", "Wu");
ComparableAs a more concrete example, lets consider the Comparable interface. java.lang provides a Comparable interface with one method, compareTo , described as follows:
You'll notice that this is the method we use to compare Strings because the String class actually implements the Comparable interface. +Revisiting our sorted list example, how would we use the Comparable interface to help us? First, we would define a SortedList class that maintained an array of Comparable objects. We would declare such an array as follows:
Comparable[] theList = new Comparable[10];
Recall that the preceding piece of code declares 10 null references, each of which can refer to something of type Comparable. Next, we would implement our add method such that it would take as input a Comparable object. The header would look as follows:
public void add(Comparable newElement) {}
Inside of the add method, we can use the compareTo method to determine whether a particular element should be shifted to the left in the list. The following condition returns true in the event that element at position i of theList comes after newElement:
theList[i].compareTo(c) > 0
Finally, we would implement a class that implements Comparable and provides an appropriate implementation of the method compareTo. As a first cut, you might try something that looks as follows:
public class ShoeSize implements Comparable {
Unfortunately, the variable o does not have a method getSize . Only objects of type ShoeSize support that method. Therefore, we must cast o to be of type ShoeSize before we invoke the getSize method. To accomplish this, we'd replace the first line of the compareTo method with the following:
ShoeSize ss = (ShoeSize)o;
|