Sun defines an interface as a named collection of method definitions (without implementations ). You define a new reference data type with a new interface. The interface name can appear anywhere a data type name can. This allows you to declare a variable's type by that interface name. You can do that with any class that implements that interface. You rarely change an interface after it's defined. Doing so breaks all classes that implemented the interface. That is why interfaces must be designed carefully , more so than concrete classes. Concrete classes are easy to change, but interfaces are hard to change. If you do change an interface, normally isolating changes in a new interface that extends the original interface is best. The subclasses of the original interface don't break, but there is still the option to upgrade to the new interface. One of Java's better known features, the Collection framework, is an excellent example of how an interface is used. The Collection framework uses a base interface, also called Collection . Listing 9.3 is an edited version of the interface. Listing 9.3 A Sample Interfacepublic interface Collection { //number of elements in this collection int size(); //true if this collection contains no elements boolean isEmpty(); //true if this collection contains the specified element. boolean contains(Object o); //iterator over the elements in this collection Iterator iterator(); //array containing all of the elements in this collection Object[] toArray(); //array containing all of the elements in this collection Object[] toArray(Object a[]); //adds the element if it isn't there boolean add(Object o); //removes the element if it is there boolean remove(Object o); //true if both collections have the same elements boolean containsAll(Collection c); //adds all of the elements in the specified collection to this collection. boolean addAll(Collection c); //removes all matching elements boolean removeAll(Collection c); //retains all matching elements boolean retainAll(Collection c); //removes all elements void clear(); //compares the specified object with this collection boolean equals(Object o); //returns the hash code value for this collection. int hashCode(); } The Collection interface is the so-called base interface for Java's Collection framework. All these methods are implemented in the concrete classes within this framework. The Set interface, a subinterface of Collection , looks like this: public interface Set extends Collection { // all the Collection methods are declared // in Set. There is no difference. } The method list in Set is exactly the same as it is in Collection . Why would Sun do that? It probably prefers having an interface with a name that's more descriptive of the functionality of classes that act like sets. That way, you can declare a reference data type as Set rather than the generic Collection . Next in the hierarchy is the SortedSet interface, shown in Listing 9.4. It extends Set , as you might expect. Listing 9.4 An Example of Extending an Abstract Classpublic interface SortedSet extends Set { //returns the comparator associated with this sorted set Comparator comparator(); //returns a view of the portion of this sorted set SortedSet subSet(Object fromElement, Object toElement); // returns a view of the portion of this sorted set whose elements are // strictly less than toElement. SortedSet headSet(Object toElement); // returns a view of the portion of this sorted set whose elements are // greater than or equal to fromElement. SortedSet tailSet(Object fromElement); // returns the first (lowest) element currently in this sorted set. Object first(); //returns the last (highest) element currently in this sorted set. Object last(); } The SortedSet interface adds a few new methods to those found in Set and Collection . These new methods provide a hint of what distinguishes the concrete class implementing this interface from the rest of the Collection classes. Listing 9.5 is an edited version of the TreeSet class provided with the J2SE 1.4 SDK, which implements SortedSet , which implements Set , which implements Collection . Listing 9.5 An Example of an Implemented Interface That Inherits from an Interfacepublic class TreeSet extends AbstractSet implements SortedSet, Cloneable, java.io.Serializable { //implementing one of the interface methods public Object clone() { TreeSet clone = null; try { clone = (TreeSet)super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } clone.m = new TreeMap(m); clone.keySet = clone.m.keySet(); return clone; } //this method is not in the interface and is new functionality private synchronized void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out any hidden stuff s.defaultWriteObject(); // Write out comparator s.writeObject(m.comparator()); // Write out size s.writeInt(m.size()); // Write out all elements in the proper order. for (Iterator i=m.keySet().iterator(); i.hasNext(); ) s.writeObject(i.next()); } //remaining code removed for space }
Interfaces Versus Abstract ClassesFor your assignment, be careful to use the right mix of interfaces and abstract classes so that your evaluator notices the clean design. To help you use these classes appropriately, the following table describes the characteristics of both side by side for comparison: Table 10.1. Comparing Abstract to Interface Classes
As you can see, there are clear differences between an interface and an abstract class. If you want to standardize only the method signatures, use an interface. Conversely, if you want to standardize method behavior, use an abstract class. In my certification solution, I did not use any abstract classes. I could have, but did not find the need to do so. However, I did use an interface for the RMI portion of the solution (See Chapter 12, "Remote Method Invocation," for more information.)
An Interface Combined with an Abstract ClassFor your assignment, you might need to combine interfaces and abstract classes. You can justify this architecture by defining the method list in the interface first. Then implement that interface in the abstract class. Provide the behavior for some of the methods in the abstract class. Finally, extend the abstract class by one or more concrete classes, in which the abstract methods of the abstract class, and any methods of the interface not overridden in the abstract class, are overridden in the concrete class. This creates a structure that demonstrates a careful use of the different class types and takes advantage of each class type. |