Interfaces
Problem: Suppose we have a collection of shapes and
we want to sort them by their area.
Solution 1: expand the definition of shape
abstract class Shape
{
double area();
double perimeter();
boolean lessThan(Shape shape)
{
return area() < shape.area() ; // don't forget about implicit this.
}
void sort(Vector of shapes)
{
code for sorting
}
}
No changes to other code.
This will work, but now we can only sort shapes. Our same
sort routine will not work for addresses or any other objects.
The C++ solution would be to allow multiple inheritance,
but Java doesn't have multiple inheritance.
The Java solution is to use interfaces, which
provide a limited type of multiple inheritance.
Sketch of Java Solution using interfaces
interface Sortable
{
boolean lessThan(Sortable o);
void sort(Sortable objects);
}
class Shape implements Sortable
{
..as before
boolean lessThan(Sortable s)
{
return area() < s.area() ;
}
no change to other classes
}
Interface Summary
- Interfaces support programming by contract, one of the
principles in object-oriented design.
- Interfaces are design artifacts, while classes mix design
and implementation.
- An interface has no member or static member functions, only
function prototypes.
- An interface may have data members, which are automatically
static and final but some compilers may require you to declare this.
- Interfaces provide a limited form of multiple inheritance.
- Interfaces collect partial similarities between dissimilar objects.
It is would be strange to force all sortable objects into a hierarchy.
- Provides contracts for concrete classes to implement.
- Promotes hiding of irrelevant procedures.
- Promotes uniformity of code, increasing simplicity.
- A class can implement any number of interfaces.
- You cannot inherit methods from an interface.
- An interface may extend other interfaces.
Standard Interface Enumeration
This interface is in java.util.*.
public abstract interface Enumeration
{
public abstract boolean hasMoreElements();
public abstract Object nextElement() throws NoSuchElementException;
}
Example use of Enumeration
Vector v = new Vector();
... fill up v with Shape objects
Enuermation e = v.elements();
while (e.hasMoreElements())
{
Shape temp = (Shape) v.nextElement(); // note cast
... process temp
}
- Interfaces permit increased comprehensibility and code sharing.
- Any class that implements this interface needs to define the
two methods above.
- StringTokenizer implements Enumeration
- Vector has a method elements() which returns an Enumeration.
Complete Sortable Example
This code illustrates appropriate commenting style. Comments of
the form //.. are explanatory and should not be included in the usual
code. This code also illustrates a few of the javadoc commands. Javadoc
commands are embedded in the comments and are preceded by @. This will
generate documentation similar to that of Sun's Java.api's.
package DataStructures; //.. this allows you bundle related class
//.. and access them via import
public interface Sortable
{
/**
* Returns 0 if objects equal,
* Returns value less than 0, if object is < tobeCompared
* Returns value greater than 0, if object is > tobeCompared
* @param toBeCompared is the object to be compared
*/
public double compare(Sortable toBeCompared);
}
package DataStructures;
import java.util.Vector; //.. that's all were using from java.util
public class Sort
{
/*
* Sorts a vector using bubbleSort.
* Bubble sort is best if number of elements is small or
* is elements are "almost" sorted.
* In worst case, bubble-sort is quadratic in number of elements.
* @param toBeStored is vector of sortable objects.
*/
public static void swap(Object o1, Object o2)
{
Object temp = o1.clone(); //.. Why necessary? Efficiency?
o1 = o2;
o2 = temp;
}
public static void bubbleSort(Vector toBeSorted)
{
int n = tobeSorted.size();
for (int i = 0; i < n; i++)
for (int j = i+1; j < n; j++)
if ( toBeSorted.elementAt(j).compare(toBeSorted.elementAt(i) ) < 0)
swap(toBeSorted.elementAt(i),toBeSorted.element(j));
}
package DataStructures;
/*
* Class that implements sortable double
*/
public class SortDouble implements Sortable
{
/* Constructs a SortDouble object
* @param val is double value
*/
public SortDouble(double val)
{
this.value = val;
}
public double val()
{
return value;
}
public double compare(Sortable toBeCompared)
{
return value - ((SortDouble) toBeCompared).val());
}
public boolean equals(Object toBeCompared)
{
return value == ((SortDouble) toBeCompare).val();
}
}
Packages
- A package is a collection of (usually) related classes and interfaces.
- The package name must be the same as the directory name, and
packages follow the directory structure.
- At most one package per directory.
- If you do not define classes to belong to a package, then
they belong to an anonymous package common to the current directory.
- The java compiler automatically imports the package java.lang.*
and the anonymous package.
- Packages are the method by which Java implements namespaces.
- The package java.util.* contains a number of miscellaneous
useful functions.
- Packages are created by prepending the line
package packagename;
before your class definition.
- To use classes provided in JDK, you begin your code with
import packagename;
- For example, the Date class is in java.util. To use this
class in your code, you use:
import java.util.*;
- Any class which is designated as belonging to a package X
has access to all other classes of package X. It is as if
"package X;" expanded to "import X; package X;".
- The package java.lang.* contains the classes for
Object, Process, String, System, Thread, Wrappers, Boolean, Character, etc.
Since these classes are almost always used, java automatically
loads this package.
- Import is not the same as include in C or C++. Import defines
where to look for class definitions; none are loaded unless used.
- In order to share classes that you have created, you need
to properly set your CLASSPATH variable. This will be covered in
the lab as it is system dependent.