Skip to content Skip to navigation

OpenStax-CNX

You are here: Home » Content » Java OOP: Polymorphism and Interfaces, Part 1

Navigation

Recently Viewed

This feature requires Javascript to be enabled.
 

Java OOP: Polymorphism and Interfaces, Part 1

Module by: R.G. (Dick) Baldwin. E-mail the author

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.

Preface

This module is one of a series of modules designed to teach you about the essence of Object-Oriented Programming (OOP) using Java.

Viewing tip

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.

Listings

Preview

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.

Discussion and sample code

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 .

Listing 1: Definition of interfaces named I1 and I2.

interface I1{
  public void p();
}//end interface I1

//===================================//

interface I2 extends I1{
  public void q();
}//end interface I2

Similar 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:

  • Methods, which are implicitly abstract
  • Variables, which are implicitly constant (final)

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 .

Listing 2: Definition of the class named A.

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

Overridden 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.

Listing 3: Definition of the class named B.

class B extends A implements I2{
  public void p(){
  }//end p()
  //---------------------------------//
  
  public void q(){
  }//end q();
  //---------------------------------//
}//end class B

Implementing 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 :

  • Extends the class named A
  • Implements the interface named I2 directly
  • Implements the interface named I1 through inheritance

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:

  • The class named B implements the interface named I2 .
  • The method named q is declared in the interface named I2 .
  • The interface named I2 extends the interface named I1 .
  • The method named p is declared in the interface named I1 .

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 .

Listing 4: Definition of the class named C.

class C extends Object implements I2{
  public void p(){
  }//end p()
  //---------------------------------//
  
  public void q(){
  }//end q();
  //---------------------------------//
}//end class B

A driver class

Finally, the driver class named Poly05 shown in Listing 5 defines an empty main method.

Listing 5: The driver class named Poly05.

public class Poly05{
  public static void main(String[] args){
  }//end main
}//end class Poly05

Doesn'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.

Summary

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:

  • Delegation event model
  • Model View Control paradigm
  • Bound and constrained properties in JavaBeans Components
  • Java Collections Framework Iterators and Enumerators

What's next?

In the next module, I will explain a more substantive program as I continue my discussion of polymorphic behavior using the Java interface.

Miscellaneous

This section contains a variety of miscellaneous information.

Note:

Housekeeping material
  • Module name: OOP 101, Polymorphism and Interfaces, Part 1
  • File: Java1616.htm
  • Published: March 27, 2002
  • Revised: July 26, 2012
  • Keywords:
    • Java interface
    • runtime polymorphism
    • abstract method
    • abstract class

Note:

Disclaimers:

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.

Complete program listings

A complete listing of the sample program is shown in Listing 6 below.

Listing 6: Complete program listing.

/*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-

Content actions

Download module as:

Add module to:

My Favorites (?)

'My Favorites' is a special kind of lens which you can use to bookmark modules and collections. 'My Favorites' can only be seen by you, and collections saved in 'My Favorites' can remember the last module you were on. You need an account to use 'My Favorites'.

| A lens I own (?)

Definition of a lens

Lenses

A lens is a custom view of the content in the repository. You can think of it as a fancy kind of list that will let you see content through the eyes of organizations and people you trust.

What is in a lens?

Lens makers point to materials (modules and collections), creating a guide that includes their own comments and descriptive tags about the content.

Who can create a lens?

Any individual member, a community, or a respected organization.

What are tags? tag icon

Tags are descriptors added by lens makers to help label content, attaching a vocabulary that is meaningful in the context of the lens.

| External bookmarks