Extending Interfaces
An interface can extend other interfaces, using the extends clause. Unlike when extending classes, an interface can extend several interfaces. The interfaces extended by an interface (directly or indirectly) are called superinterfaces. Conversely, the interface is a subinterface of its superinterfaces. Since interfaces define new reference types, superinterfaces and subinterfaces are also supertypes and subtypes, respectively.
A subinterface inherits from its superinterfaces all members of those superinterfaces, except for the following:
- Any abstract or default methods that it overrides from its superinterfaces (p. 240 and p. 246)
- Any static methods declared in its superinterfaces (p. 251)
- Any static constants that it hides from its superinterfaces (p. 254)
- Any static member types that it hides from its superinterfaces (§9.2, p. 495)
Barring any conflicts, a subinterface inherits abstract and default method declarations that are not overridden, as well as constants and static member types that it does not hide in its superinterfaces. In addition, abstract, static, and default method declarations can be overloaded, analogous to method overloading in classes. For a detailed discussion of overriding abstract methods from multiple superinterfaces, see §11.12, p. 621.
Example 5.10 illustrates the relationships between classes and interfaces. In Example 5.10, the interface ISafeStack extends the interface IStack at (5). The class SafeStack both extends the Stack class and implements the ISafeStack interface at (6). Inheritance hierarchies for classes and interfaces defined in Example 5.10 are shown in Figure 5.4.
In UML, an interface resembles a class. One way to differentiate between them is to use an «interface» stereotype, as in Figure 5.4. The association between a class and any interface it implements is called a realization in UML. Realization is depicted in a similar manner to extending classes, but is indicated by an unbroken inheritance arrow. In Figure 5.4, there are two explicit realizations: The class Stack implements the IStack interface and the class SafeStack implements the ISafeStack interface.
It is instructive to consider how the class SafeStack transitively also implements the IStack interface in Example 5.10. This is evident from the diamond shape of the inheritance hierarchy in Figure 5.4. The class SafeStack inherits the implementations of the push() and pop() methods from its superclass Stack, which itself implements the
Figure 5.4 Inheritance Hierarchies for Classes and Interfaces in Example 5.10
IStack interface in which these two methods are declared. The class SafeStack also implements the IStack interface via the ISafeStack interface. The class SafeStack provides its own implementation of the isFull() and isEmpty() methods declared in the ISafeStack interface, and has inherited implementations of the push() and pop() methods whose declarations the ISafeStack interface inherits from its super-interface IStack. Note that there is only one implementation of a method that is inherited by the class SafeStack—from its superclass Stack.
Thinking in terms of types, every reference type in Java is a subtype of the java.lang.Object class. In turn, any interface type is also a subtype of the Object class, but it does not inherit any implementation from the Object class. As mentioned earlier, an interface that has no direct superinterfaces implicitly declares a public abstract method for each public instance method in the Object class. These abstract method declarations are inherited by all subinterfaces of such an interface. Note that this does not mean any implementation is inherited by the subinterfaces. The implicit public abstract method declarations in an interface allow public instance methods in the Object class to be invoked on objects referenced by an interface reference. All classes implement these methods, whether they are inherited or overridden from the Object class. Any interface can also provide explicit public abstract method declarations for non-final public instance methods in the Object class.
interface IStack { // (1)
void push(Object item);
Object pop();
@Override boolean equals(Object other); // public method in Object class.
@Override String toString(); // public method in Object class.
//@Override Class getClass(); // Compile-time error! final method in Object class.
}