Summary: According to Baldwin, if you don't understand the Java interface, you don't understand Java. There is very little, if anything useful that can be done using Java without understanding and using the Java interface.
Note: You are viewing an old version of this document. The latest version is available here.
This module is one of a series of modules designed to teach you about the essence of Object-Oriented Programming (OOP) using Java.
I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the listings while you are reading about them.
Method overloading
I covered method overloading as one form of polymorphism (compile-time polymorphism) in a previous module. I also explained automatic type conversion and the use of the cast operator for type conversion in a previous module.
Method overriding and class inheritance
I also discussed runtime polymorphism implemented through method overriding and class inheritance in previous modules.
Using the Java interface
In this module and the next, I will explain runtime polymorphism as implemented using method overriding and the Java interface.
A very important concept
In my opinion, this is one of the most important concepts in Java OOP, and the one that seems to give students the greatest amount of difficulty. Therefore, I will try to take it slow and easy. As usual, I will illustrate the concept using sample programs.
I will also tie this concept back to the concept of polymorphism using method overriding through inheritance.
A skeleton program
In this module, I will present a simple skeleton program that illustrates many of the important aspects of polymorphic behavior based on the Java interface.
Multiple inheritance and the cardinal rule
I will explain how the implementation of interfaces in Java is similar to multiple inheritance. I will explain the cardinal rule of interface implementation.
A new relationship
I will explain that objects instantiated from classes that implement the same interface have a new relationship that goes beyond the relationship imposed by the standard class hierarchy.
One object, many types
I will explain that due to the combination of the class hierarchy and the fact that a class can implement many different interfaces, a single object in Java can be treated as many different types. However, for any given type, there are restrictions on the methods that can be called on the object.
Many classes, one type
I will explain that because different classes can implement the same interface, objects instantiated from different classes can be treated as a common interface type.
Interfaces are critical to Java programming
I will suggest that there is little if anything useful that can be done in Java without understanding and using interfaces.
In support of this suggestion, I will discuss several real-world examples of the use of the Java interface, including the Delegation Event Model, the Model View Control paradigm, and iterators in Java data structures.
Listing 6 near the end of the module contains a very simple program named Poly05 .
The purpose of this program is to illustrate polymorphic behavior using interfaces in addition to class inheritance.
Designed to illustrate structure
This is a skeleton program designed solely to illustrate the inheritance and interface implementation structure in as simple a program as possible. (I will put some meat on this skeleton using another program in the next module.)
Empty methods
Except for the two methods that return type String , all of the methods in the program are empty. (Methods that return type String cannot be empty. They must contain a return statement in order to compile successfully.)
Interface definitions
Listing 1 shows the definition of two simple interfaces named I1 and I2 .
interface I1{
public void p();
}//end interface I1
//===================================//
interface I2 extends I1{
public void q();
}//end interface I2Similar but different
An interface definition is similar to a class definition. However, there are some very important differences.
No single hierarchy
To begin with, unlike the case with classes, there is no single interface hierarchy. Also, multiple inheritance is allowed when extending interfaces.
A new interface can extend none, one, or more existing interfaces. In Listing 1 , I2 extends I1 , but I1 doesn't extend any other interface (and unlike classes, an interface doesn't automatically extend another interface by default) .
Two kinds of members allowed
Only two kinds of members are allowed in an interface definition:
Each of the interfaces in Listing 1 declares an implicitly abstract method (an abstract method does not have a body) .
Neither of the interfaces in Listing 1 declares any variables (they aren't needed for the purpose of this module) .
A new data type
I told you earlier that when you define a new class, you cause a new data type to become available to your program. The same is true of an interface definition. Each interface definition constitutes a new type.
The class named A
Listing 2 defines a very simple class named A , which in turn defines two methods named toString and x .
class A extends Object{
public String toString(){
return "toString in A";
}//end toString()
//---------------------------------//
public String x(){
return "x in A";
}//end x()
//---------------------------------//
}//end class AOverridden toString
The method named toString in Listing 2 is actually an overridden version of the method having the same name that is defined in the class named Object . (Recall that a previous module made heavy use of overridden versions of the toString method.)
New method
The method named x is newly defined in the class named A . (The method named x is not inherited into the class named A , because the class named Object does not define a method named x .)
The class named B
Listing 3 contains material that is new to this module.
class B extends A implements I2{
public void p(){
}//end p()
//---------------------------------//
public void q(){
}//end q();
//---------------------------------//
}//end class BImplementing an interface
Listing 3 defines a class named B , which extends the class named A , and implements the interface named I2 .
As you already know, a class in Java can extend only one other class. However, a Java class can implement any number of interfaces. (Multiple inheritance is allowed with interfaces.)
Similar to an abstract class
An interface is similar, but not identical, to an abstract class. (An abstract class may contain abstract methods or concrete methods, or a combination of the two while all of the methods in an interface are implicitly abstract.)
Restrictions
An abstract class cannot be instantiated. Thus, an abstract class is only useful when it is extended by another class.
An interface also cannot be instantiated.
Implicitly abstract methods
As mentioned above, all methods declared in an interface are implicitly abstract, but that is not true for an abstract class. An abstract class can also contain fully-defined (concrete) methods. Regardless, an abstract class cannot be instantiated.
A totally abstract class
At the risk of offending the purists, I will coin a new term here and say that an interface is similar to a totally abstract class (one which contains only abstract method declarations and final variables) .
To a first degree of approximation then, we might say that the class named B is not only a subclass of the class named A , it is also a subclass of the totally abstract class named I2 . (This is pretty far out with respect to terminology, so to avoid being embarrassed, you probably shouldn't repeat it to anyone else.)
Since I2 extends I1 , we might also say that the class named B is a subclass of the totally abstract class named I1 .
A different kind of thinking
With this kind of thinking, we have suddenly make it possible for Java classes to support multiple inheritance , with the stipulation that all but one of the inherited classes must be totally abstract classes .
Be very careful with this way of thinking
However, we need to be very careful with this kind of thinking. While it may help some students to understand the role of interfaces in Java, there are probably some hidden dangers lurking here.
Back to the safety zone
The safest course of action is to simply say that the class named B :
Java does not support multiple inheritance, but it does allow you to extend one class and implement any number of interfaces.
The cardinal rule regarding interface implementation
The cardinal rule in implementing interfaces is:
If a class implements an interface, it must provide a concrete definition for all the methods declared by that interface, and all the methods inherited by that interface. Otherwise, the class must be declared abstract and the definitions must be provided by a class that extends the abstract class.
The cardinal rule regarding class inheritance
A similar rule exists for defining classes that inherit abstract methods from other classes:
If a class inherits one or more abstract methods from its superclasses, it must provide concrete definitions for all the inherited abstract methods. Otherwise, the class must be declared abstract and the concrete definitions must be provided by a class that extends the abstract class.
What does that mean in this case?
In this case, this means that the class named B must provide concrete definitions for the methods named p and q , because:
As in method overriding, the signature of the concrete method in the defining class must match the signature of the method as it is declared in the interface.
Class B satisfies the cardinal rule
As you can see from Listing 3 , the class named B does provide concrete (but empty) definitions of the methods named p and q .
(As mentioned earlier, I made the methods empty in this program for simplicity. However, it is not uncommon to define empty methods in classes that implement interfaces that declare a large number of methods, such as the MouseListener interface. See my tutorials on event-driven programming at http://www.dickbaldwin.com/toc.htm for examples.)
The class named C
Listing 4 defines a class named C , which extends Object , and also implements I2 . As in the case of the class named B , this class must, and does, provide concrete (but empty) definitions for the methods named p and q .
class C extends Object implements I2{
public void p(){
}//end p()
//---------------------------------//
public void q(){
}//end q();
//---------------------------------//
}//end class BA driver class
Finally, the driver class named Poly05 shown in Listing 5 defines an empty main method.
public class Poly05{
public static void main(String[] args){
}//end main
}//end class Poly05Doesn't do anything
As mentioned earlier, the purpose of this program is solely to illustrate an inheritance and interface structure. This program can be compiled and executed, but it doesn't do anything useful.
A new relationship
At this point, it might be useful for you to sketch out the structure in a simple hierarchy diagram.
If you do, you will see that implementation of the interface named I2 by the classes named B and C , has created a relationship between those two classes that is totally independent of the normal class hierarchical relationship.
What is the new relationship?
By declaring that both of these classes implement the same interface named I2 , we are guaranteeing that an object of either class will contain concrete definitions of the two methods declared in the interfaces named I2 and I1 .
Furthermore, we are guaranteeing that objects instantiated from the two classes can be treated as the common type I2 .
( Important : references to any objects instantiated from classes that implement I2 , can be stored in reference variables of the type I2 , and any of the interface methods can be called on those references.)
We know the user interface
The signatures of the interface methods in the two classes must match the signatures declared in the interfaces.
This means that if we have access to the documentation for the interfaces, we also know the signatures of the interface methods for objects instantiated from any class that implements the interfaces.
Different behavior
However, and this is extremely important, the behavior of the interface methods as defined in the class named B may be (and often will be) entirely different from the behavior of the interface methods having the same signatures as defined in the class named C .
Possibly the most powerful concept in Java
This is possibly the most powerful (and most difficult) concept embodied in the Java programming language.
If you don't understand interfaces ...
I usually tell my students several times each semester that if they don't understand interfaces, they don't really understand Java.
It is unlikely that you will ever be successful as a Java programmer without an understanding of interfaces.
There are very few worthwhile programs that can be written in Java without an understanding of interfaces.
The core aspect
So, what is the core aspect of this concept that is so powerful?
I told you earlier that each interface definition constitutes a new type. As a result, a reference to any object instantiated from any class that implements a given interface can be treated as the type of the interface.
So what!
When a reference to an object is treated as an interface type, any method declared in, or inherited into that interface can be called on the reference to the object.
However, the behavior of the method when called on references to different objects of the same interface type may be very different. In the current jargon, the behavior is appropriate for the object on which it is called .
One object, many types
Furthermore, because a single class can implement any number of different interfaces, a single object instantiated from a given class can be treated as any of the interface types implemented by the class from which it is instantiated. Therefore, a single object in Java can be treated as many different types.
(However, when an object is treated as an interface type, only those methods declared in that interface can be called on the object. To call other methods on the object, it necessary to cast the object's reference to a different type.)
Treating different types of objects as a common type
All of this also makes it possible to treat objects instantiated from widely differing classes as the same type, provided that all of those classes implement the same interface.
Important : When an interface method is called on one of the objects using the reference of the interface type, the behavior of the method will be as defined by the author of the specific class that implemented the interface. The behavior of the method will often be different for different objects instantiated from different classes that implement the same interface.
Receiving parameters as interface types
Methods can receive parameters that are references of interface types. In this case, the author of the code that calls interface methods on the incoming reference doesn't need to know, and often doesn't care, about the name of the class from which the object was instantiated. (For a discussion of this capability, see my tutorials on Java Data Structures on my web site at http://www.dickbaldwin.com/toc.htm .)
A common example
A very common example is to store references to objects instantiated from different classes, (which implement the same interface) in some sort of data structure ( such as list or a set) and then to call the same methods on each of the references in the collection.
Heart of the Delegation Event Model
For example, this methodology is at the heart of the Delegation Event Model , which forms the basis of Graphical User Interfaces and event-driven programming in Java.
This often entails defining classes that implement standard interfaces such as MouseListener , WindowListener , TextListener , etc. In this case, the programmer defines the interface methods to be appropriate for a listener object instantiated from a specific class. Then a reference to the listener object is registered on an event source as the interface type .
Later when an event of that type occurs, the source object calls one or more interface methods on the listener object using the reference of the interface type. The event source object doesn't know or care about the class from which the object was instantiated. In fact, it doesn't even care how the interface method behaves when it is called. The responsibility of the source object ends when it calls the appropriate interface method on the listener object.
Model View Control
This same methodology is also critical to the use of the Model View Control paradigm in Java using the Observer interface and the Observable class. In this case, view objects instantiated from different classes that implement the Observer interface can register themselves on a model object that extends the Observable class. Then each time the data being maintained in the model changes, each of the views will be notified so that they can update themselves.
JavaBeans Components
This concept is also critical to the use of bound and constrained properties in JavaBeans Components. One bean can register itself on other beans to be notified each time the value of a bound or constrained property changes. In the case of constrained properties, the bean that is notified has the option of vetoing the change.
Java Collections Framework
The Java Collections Framework is also totally dependent on the use of interfaces. As I mentioned earlier, you can read all about this in my modules on Java Data Structures.
Iterators and Enumerators
If you appreciate data structures, you will also appreciate iterators. In Java, Iterator is an interface, and an object that knows how to iterate across a data structure is an object of a class that implements the Iterator interface.
As a result, the users of the concrete implementations in the Java Collections Framework don't need to know any of the implementation details of the collection to create and use an iterator. All of the work necessary to properly create an iterator is done by the author of the class that implements the appropriate Collection interfaces. All the user needs to understand is the behavior of the three methods declared in the Iterator interface.
Polymorphic behavior, based on the Java interface, is one of the most important concepts in Java OOP
In this module, I began my discussion of runtime polymorphism as implemented using method overriding and the Java interface.
I presented a simple skeleton program that illustrated many of the important aspects of polymorphic behavior based on the Java interface.
By using a nonstandard notation of my own design, (a totally abstract class) , I explained how the implementation of interfaces in Java is similar to multiple inheritance.
I explained the cardinal rule, which is:
If a class implements an interface, it must provide a concrete definition for all the methods declared by that interface, and all the methods inherited by that interface. Otherwise, the class must be declared abstract and the definitions must be provided by a class that extends the abstract class.
I explained that objects instantiated from classes that implement the same interface have a new relationship that goes beyond the relationship imposed by the standard class hierarchy.
I explained that due to the combination of the class hierarchy and the fact that a class can implement many different interfaces, a single object in Java can be treated as many different types. However, for any given type, there are restrictions on the methods that can be called on the object.
I also explained that because different classes can implement the same interface, objects instantiated from different classes can be treated as a common interface type.
I suggested that there is little if anything useful that can be done in Java without understanding and using interfaces.
Finally I discussed some real-world examples of the use of the Java interface:
In the next module, I will explain a more substantive program as I continue my discussion of polymorphic behavior using the Java interface.
This section contains a variety of miscellaneous information.
Financial : Although the Connexions site makes it possible for you to download a PDF file for this module at no charge, and also makes it possible for you to purchase a pre-printed version of the PDF file, you should be aware that some of the HTML elements in this module may not translate well into PDF.
I also want you to know that, I receive no financial compensation from the Connexions website even if you purchase the PDF version of the module.
In the past, unknown individuals have misappropriated copies of my modules from cnx.org, converted them to Kindle books, and placed them for sale on Amazon.com showing me as the author. I receive no compensation for those sales and don't know who does receive compensation. If you purchase such a book, please be aware that it is a bootleg copy of a module that is freely available on cnx.org.
Affiliation :: I am a professor of Computer Information Technology at Austin Community College in Austin, TX.
A complete listing of the sample program is shown in Listing 6 below.
/*File Poly05.java
Copyright 2002, R.G.Baldwin
**************************************/
interface I1{
public void p();
}//end interface I1
//===================================//
interface I2 extends I1{
public void q();
}//end interface I2
//===================================//
class A extends Object{
public String toString(){
return "toString in A";
}//end toString()
//---------------------------------//
public String x(){
return "x in A";
}//end x()
//---------------------------------//
}//end class A
//===================================//
class B extends A implements I2{
public void p(){
}//end p()
//---------------------------------//
public void q(){
}//end q();
//---------------------------------//
}//end class B
//===================================//
class C extends Object implements I2{
public void p(){
}//end p()
//---------------------------------//
public void q(){
}//end q();
//---------------------------------//
}//end class B
//===================================//
public class Poly05{
public static void main(String[] args){
}//end main
}//end class Poly05-end-