Suppose you wanted your Employee classes to have a standard behavior, such as the ability to be sorted — so that you could list your employees in a report, perhaps.

You could add this capability to the Employee class, and all its subclasses would inherit that capability, also.

On further reflection, however, you realize that the capability of being sorted is potentially usable by other classes beyond just employees.

So, you write an abstract class Sortable:

package sortable;

public abstract class Sortable
{
    public abstract int compare(Sortable rhs);

    public static void shellSort(Sortable[] a)
    {
        int n = a.length;
        int incr = n/2;
        while (incr >= 1)
        {
            for (int i = incr; i < n; i++)
            {
                Sortable temp = a[i];
                int j = i;
                while ((j >= incr) &&
                       (temp.compare(a[j - incr]) < 0)
                      )
                {
                    a[j] = a[j - incr];
                    j -= incr;
                }
                a[j] =temp;
            }
            incr /= 2;
        }
    }
}

And modify the Employee class to inherit from it:

package company;

import java.util.Date;
import sortable.Sortable;

public class Employee extends Sortable
{
    // Compare, based on salary
    public int compare(Sortable rhs)
    {
        Employee eb = (Employee) rhs;
        if (m_salary < eb.m_salary) return -1;
        if (m_salary > eb.m_salary) return 1;
        return 0;
    }
    // ...
}

Then, we can modify the test program to use the sorting capability:

package company;

import java.util.Date;
import sortable.Sortable;

public class CompanyTest
{
    public static void main(String[] args)
    {
        Employee[] staff = new Employee[6];

	// ...

        Sortable.shellSort(staff);
        for (int i = 0; i < staff.length; i++)
            staff[i].print();
    }
}

This works fine.

What’s the Problem?

So, you might say, what’s the problem?

What if you wanted to add additional capabilities to the employee classes, such as PersistentCloneable, etc.?

You could write an abstract class for each one, and then try to get class Employee to use them all:

package company;

import sortable.Sortable;
import persistent.Persistent;
import cloneable.Cloneable;  // Fictitious!

public class Employee extends Sortable, Persistent, Cloneable
{
    // ...
}

Unfortunately, Java gives you compile-time errors if you try it.

Why?

The Solution

As you probably guessed, the solution is to use interfaces instead of classes.

Here’s an interface called Sortable:

package sortable;

public interface Sortable
{
    public int compare(Sortable rhs);
}

We have to place the shellSort() method in a separate class, because Java doesn’t let us implement any methods in an interface:

package sortable;

public abstract class Sort
{
    public static void shellSort(Sortable[] a)
    {
        int n = a.length;
        int incr = n/2;
        while (incr >= 1)
        {
            for (int i = incr; i < n; i++)
            {
                Sortable temp = a[i];
                int j = i;
                while ((j >= incr) &&
                       (temp.compare(a[j - incr]) < 0)
                      )
                {
                    a[j] = a[j - incr];
                    j -= incr;
                }
                a[j] =temp;
            }
            incr /= 2;
        }
    }
}

Note that we made class Sort abstract, because we never need an instance of it; it contains exactly one method, which is a static method.  (Another example of an abstract class that only contains static methods is the Math class.)  

And we must then modify the Employee class as follows:

package Employees;
import java.util.Date;
import Sortable.Sortable;

public class Employee implements Sortable
{
    public int compare(Sortable rhs)
    {
        Employee eb = (Employee) rhs;
        if (m_salary < eb.m_salary) return -1;
        if (m_salary > eb.m_salary) return 1;
        return 0;
    }
    // ...
}

Note that we use the implements keyword to specify that a class uses an interface, as opposed to the extends keyword.

The test code looks similar to before:

package company;

import java.util.Date;
import sortable.Sort;

public class CompanyTest
{
    public static void main(String[] args)
    {
        Employee[] staff = new Employee[6];

	// ...

        Sort.shellSort(staff);
        for (int i = 0; i < staff.length; i++)
            staff[i].print();
    }
}

Why is that better?

So, why do we think that using interfaces is better, in this case?

Using interfaces in Java is essential for adding certain functionality.  For example, we can now add other capabilities simultaneously using additional interfaces:

package company;

import sortable.Sortable;
import persistent.Persistent;
import cloneable.Cloneable; // Fictitious!

public class Employee implements Sortable, Persistent, Cloneable
{
    // ...
}

Note the keyword implements in place of extends, and the fact that you can now specify a comma-separated list of interface names.

This is valid syntax, and compiles without error.

Multiple Inheritance

Single vs. Multiple Inheritance

Java allows a class to inherit from only a single superclass.  This is called single inheritance.

In contrast, C++ supports both single and multiple class inheritance.  Experience has shown, however, that using multiple inheritance is often problematic;  it is very complex, rife with pitfalls, and is one of the most difficult and non-intuitive features of that language. Using uncontrolled multiple inheritance can be dangerous to your sanity!

However, Java does allow a class to implement many interfaces. 

We say that Java supports:

  • Single implementation inheritance (extend from a superclass)
  • Multiple interface inheritance (implement zero or more interfaces)

As a result, Java avoids the horrible problems of generalized multiple inheritance. 

What is an Interface?

So, What is an Interface?

An interface has the following properties:

  • It is a type, just as a class is a type.
  • It may contain:
    • abstract method declarations (no implementations).  
      • Such methods are always (implicitly) public.
    • field (data) declarations that are implicitly publicstatic and final
      • synchronizedtransient and volatile are not allowed
  • It may not be instantiated

Basically, an interface is similar to an abstract class that contains:

  • no method implementations, and
  • no instance fields

Interfaces allow you to “add in” multiple behaviors for a class. If you want to instantiate such a class, that class must implement all the abstract methods from all the interfaces it has said it implements.  If that class does not implement the abstract methods from its interfaces, then that class is abstract.

The ability for a class to implement a number of interfaces amounts to multiple interface inheritance

Java’s more restricted form of multiple inheritance is a much safer form than the more general multiple inheritance supported by C++. The trickiest area of multiple inheritance is when you are trying to inherit multiple implementations; if you restrict multiple inheritance to multiple interface inheritance, most of the problems go away.

Interface “Contracts”

One way to look at an interface is to consider it to be a “contract“.  Any class that specifies it implements that interface is “contractually obligated” to implement all the (abstract) methods specified in the interface.

Such a “contract” only specifies that there be an implementation, not how it might be implemented.

Nouns vs. Adjectives

One clue to help you choose whether to use a class or an interface has to do with parts of speech.

If you recall, in English, there are the following parts of speech:

  • Verbs (is, does, makes, travels, reads, invents, and so on)
  • Nouns (book, class, student, thought, John, etc.)
  • Pronouns (he, she, it, you, them, which, mine, etc.)
  • Adjectives (wet, dry, dark, light, my, your, bedraggled, etc.)
  • Adverbs (finely, well, quickly, unfortunately, etc.)
  • Prepositions (on, about, among, behind, etc.)
  • Conjunctions (and, but, for, after, because, etc.)
  • Interjections (ouch!, yikes!, hey!, Gadzooks!, eh? [especially in Canada ;)] )

If you are designing your program in an Object-Oriented way, you should be thinking about the objects that your program will be dealing with.  These objects can be relatively concrete, such as Person, Employee, Dog, Gorilla, etc., or they can be more ethereal, such as Idea, Relationship, Reputation, and so on.  Each of these objects is therefore somewhat naturally represented by a name.

class represents such an object, and so the most natural name for such a class is a noun — the name of the object. Sometimes, it is easy to determine an appropriate name, and sometimes less so. (I am a firm believer in spending time choosing an appropriate name for a class, because it represents what my program is trying to model.  If I choose wisely, many of the questions that arise can be answered relatively easily;  if I do not, things get harder.)

You may have noticed that the interfaces we’ve looked at so far have names like Cloneable, Sortable, Serializable, and so on.  These are adjectives, rather than nouns, and this convention is fairly typical.

So, here are some simple rules of thumb about naming:

  • Class — normally use a noun
  • Interface — often use an adjective, but nouns are often used, too
  • Method — normally use an imperative verb.

These aren’t iron-clad rules, but I would definitely think twice before violating them — and fully justify my choice!

Appropriate choices (which come more easily with experience and an awareness of need) will often make things easier for you as you progress in the design and implementation of your program.

Interface Inheritance

Superinterfaces and Subinterfaces

As we have said, a class may implement zero or more interfaces.

In addition, an interface may inherit (keyword extends) from one or more other superinterfaces.

interface BaseColors
{
    int RED = 1, GREEN = 2, BLUE = 3;
}
interface RainbowColors extends BaseColors
{
    int YELLOW = 3, ORANGE = 5, INDIGO = 6, VIOLET = 7;
}
interface PrintColors extends BaseColors
{
    int YELLOW = 8, CYAN = 16, MAGENTA = 32;
}
interface FancyColors extends RainbowColors, PrintColors
{
    int FUCHSIA = 17,
        VERMILLION = 43,
        CHARTREUSE = RED + 90;
}

Note: Be careful with ambiguous inherited fields (YELLOW, above)!

The interfaces named in the extends clause for a class are the direct superinterfaces for that class.

Any class that implements the declared interface is also considered to implement all the interfaces that this interface extends and that are accessible to the class.

Marker Interfaces

Surprisingly, it is possible to define an interface that is entirely empty!

Why is this useful?

A class can implement this interface simply to provide additional information about itself.

We will soon see an example of a marker interface (Cloneable).