Java Advanced Placement Study Guide:  Interfaces and polymorphic behavior

Sample question:  What happens if a class inherits a method with a given signature and also implements one or more interfaces that declare a method with an identical signature?

Published: January 1,  2004
By Richard G. Baldwin

Questions

File JavaAP024.htm


Welcome

This is one in a miniseries of tutorial lessons designed to help you learn the essential features of Java object-oriented programming as identified by The College Board.

Purpose

The purpose of this miniseries is to help you study for the Advanced Placement Examinations designed by the College Board.

Once you understand everything in this miniseries, plus the material in the lessons that I published earlier on Java Data Structures, you should understand the Java programming features that the College Board considers essential for the first two semesters of object-oriented programming education at the university level.

Approach

These lessons provide questions, answers, and explanations designed to help you to understand the subset of Java features covered by the Java Advanced Placement Examinations (as of October, 2001).

Please see the first lesson in the miniseries entitled Java Advanced Placement Study Guide: Introduction to the Lessons, Primitive Types, for additional background information.  The previous lesson was entitled Java Advanced Placement Study Guide:  Extending Classes, Overriding Methods, and Polymorphic Behavior.

Supplementary material

In addition to the material in these lessons, I recommend that you also study the other lessons in my extensive collection of online Java tutorials, which are designed from a more conventional textbook approach.  You will find those lessons published at Gamelan.com.  However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there.  You will find a consolidated index at Baldwin's Java Programming Tutorials.

What is Included?

Click here for a preview of the Java programming features covered by this lesson.



1.  What output is produced by the following program?
public class Ap131{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap131

class Worker{
  void doIt(){
    Base myVar1 = new Base();
    myVar1.inherMethod();
    X myVar2 = new A();
    myVar2.intfcMethod();

    System.out.println("");
  }//end doIt()
}// end class Worker

class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

class A extends Base{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethod(){
    System.out.print("A-intfcMethod ");
  }//end intfcMethod()
}//end class A

interface X{
  public void intfcMethod();
}//end X

Answer and Explanation

2.  What output is produced by the following program?

public class Ap132{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap132

class Worker{
  void doIt(){
    Base myVar1 = new Base();
    myVar1.inherMethod();
    Base myVar2 = new A();
    myVar2.intfcMethod();

    System.out.println("");
  }//end doIt()
}// end class Worker

class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethod(){
    System.out.print("A-intfcMethod ");
  }//end intfcMethod()
}//end class A

interface X{
  public void intfcMethod();
}//end X

Answer and Explanation

3.  What output is produced by the following program?

public class Ap133{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap133

class Worker{
  void doIt(){
    Base myVar1 = new Base();
    myVar1.inherMethod();
    A myVar2 = new A();
    myVar2.intfcMethod();

    System.out.println("");
  }//end doIt()
}// end class Worker

class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethod(){
    System.out.print("A-intfcMethod ");
  }//end intfcMethod()
}//end class A

interface X{
  public void intfcMethod();
}//end X

Answer and Explanation

4.  What output is produced by the following program?

public class Ap134{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap134

class Worker{
  void doIt(){
    Base myVar1 = new Base();
    myVar1.inherMethod();
    X myVar2 = new A();
    myVar2.intfcMethod();

    System.out.println("");
  }//end doIt()
}// end class Worker

class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethod(){
    System.out.print("A-intfcMethod ");
  }//end intfcMethod()
}//end class A

interface X{
  public void intfcMethod();
}//end X

Answer and Explanation

5.  What output is produced by the following program?

public class Ap135{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap135

class Worker{
  void doIt(){
    X myVar1 = new A();
    myVar1.intfcMethodX();
    X myVar2 = new B();
    myVar2.intfcMethodX();

    System.out.println("");
  }//end doIt()
}// end class Worker

class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "A-intfcMethodX ");
  }//end intfcMethodX()
}//end class A

class B extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " B-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "B-intfcMethodX ");
  }//end intfcMethodX()
}//end class B

interface X{
  public void intfcMethodX();
}//end X

Answer and Explanation

6.  What output is produced by the following program?

public class Ap136{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap136

class Worker{
  void doIt(){
    Object[] myArray = new Object[2];
    myArray[0] = new A();
    myArray[1] = new B();
    
    for(int i=0;i<myArray.length;i++){
      myArray[i].intfcMethodX();
    }//end for loop

    System.out.println("");
  }//end doIt()
}// end class Worker

class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "A-intfcMethodX ");
  }//end intfcMethodX()
}//end class A

class B extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " B-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "B-intfcMethodX ");
  }//end intfcMethodX()
}//end class B

interface X{
  public void intfcMethodX();
}//end X

Answer and Explanation

7.  What output is produced by the following program?

public class Ap137{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap137

class Worker{
  void doIt(){
    Object[] myArray = new Object[2];
    myArray[0] = new A();
    myArray[1] = new B();
    
    for(int i=0;i<myArray.length;i++){
      ((X)myArray[i]).intfcMethodX();
    }//end for loop

    System.out.println("");
  }//end doIt()
}// end class Worker

class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "A-intfcMethodX ");
  }//end intfcMethodX()
}//end class A

class B extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " B-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "B-intfcMethodX ");
  }//end intfcMethodX()
}//end class B

interface X{
  public void intfcMethodX();
}//end X

Answer and Explanation

8.  What output is produced by the following program?

public class Ap138{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap138

class Worker{
  void doIt(){
    X[] myArray = new X[2];
    myArray[0] = new A();
    myArray[1] = new B();
    
    for(int i=0;i<myArray.length;i++){
      myArray[i].intfcMethodX();
    }//end for loop

    System.out.println("");
  }//end doIt()
}// end class Worker

class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "A-intfcMethodX ");
  }//end intfcMethodX()
}//end class A

class B extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " B-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "B-intfcMethodX ");
  }//end intfcMethodX()
}//end class B

interface X{
  public void intfcMethodX();
}//end X

Answer and Explanation

9.  What output is produced by the following program?

public class Ap139{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap139

class Worker{
  void doIt(){
    Base myVar = new Base();
    myVar.test();
    myVar = new A();
    myVar.test();
    myVar = new B();
    myVar.test();
    System.out.println("");
  }//end doIt()
}// end class Worker

class Base{
  public void test(){
    System.out.print("Base ");
  }//end test()
}//end class Base

class A extends Base implements X,Y{
  public void test(){
    System.out.print("A ");
  }//end test()
}//end class A

class B extends Base implements X,Y{
  public void test(){
    System.out.print("B ");
  }//end test()
}//end class B

interface X{
  public void test();
}//end X

interface Y{
  public void test();
}//end Y

Answer and Explanation

10.  What output is produced by the following program?

public class Ap140{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap140

class Worker{
  void doIt(){
    Base myVar1 = new Base();
    myVar1.test();
    myVar1 = new A();
    myVar1.test();
    myVar1 = new B();
    myVar1.test();

    X myVar2 = (X)myVar1;
    myVar2.test();

    System.out.println("");
  }//end doIt()
}// end class Worker

class Base{
  public void test(){
    System.out.print("Base ");
  }//end test()
}//end class Base

class A extends Base implements X,Y{
  public void test(){
    System.out.print("A ");
  }//end test()
}//end class A

class B extends Base implements X,Y{
  public void test(){
    System.out.print("B ");
  }//end test()
}//end class B

interface X{
  public void test();
}//end X

interface Y{
  public void test();
}//end Y

Answer and Explanation



Copyright 2002, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java and XML. In addition to the many platform-independent benefits of Java applications, he believes that a combination of Java and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects involving Java, XML, or a combination of the two.  He frequently provides onsite Java and/or XML training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Java Programming Tutorials, which has gained a worldwide following among experienced and aspiring Java programmers. He has also published articles on Java Programming in Java Pro magazine.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

baldwin.richard@iname.com


What is Included?

According to the subset document: Note that abstract classes are not included in this lesson.  They were included in an earlier lesson.


Answers and Explanations

Answer 10

C.  Base A B B

Back to Question 10

Explanation 10

Expansion of the program from Question 9

The class and interface definitions for the classes and interfaces named Base, A, B, X, and Y are the same as in Question 9.

Invoke the test method differently

However, the invocation of the method named test() in the object instantiated from the class named B is somewhat different.  The difference is identified by the boldface code in the following fragment.
 
  void doIt(){
    Base myVar1 = new Base();
    myVar1.test();
    myVar1 = new A();
    myVar1.test();
    myVar1 = new B();
    myVar1.test();

Invoking test method on Base-type reference

In Question 9, and in the above code fragment as well (shown in Italics) the method named test() was invoked on each of the objects using a reference stored in a reference variable of type Base.

Invoking the overridden version of test method

This might be thought of as invoking the overridden version of the method, through polymorphism, without regard for anything having to do with the interfaces.

Invoking test method on interface-type reference

The boldface code in the next fragment invokes the same method named test() on one of the same objects using a reference variable of the interface type X.
 
    X myVar2 = (X)myVar1;
    myVar2.test();

    System.out.println("");
  }//end doIt()

Only one test method in each object

Keep in mind that each object defines only one method named test().  This single method serves the dual purpose of overriding the method having the same signature from the superclass, and implementing a method with the same signature declared in each of the interfaces.

Implementing the interface method

Perhaps when the same method is invoked using a reference variable of the interface type, it might be thought of as implementing the interface method rather than overriding the method defined in the superclass.

The same method is invoked regardless of reference type

In any event, in this program, the same method is invoked whether it is invoked using a reference variable of the superclass type, or using a reference variable of the interface type.

Illustrates the behavior of signature collisions

The purpose of this and the previous question is not necessarily to illustrate a useful inheritance and implementation construct.  Rather, these two questions are intended to illustrate the behavior of Java for the case of duplicated superclass and interface method signatures.

Answer 9

C.  Base A B

Back to Question 9

Explanation 9

A question regarding signature collisions

The question often arises in my classroom as to what will happen if a class inherits a method with a given signature and also implements one or more interfaces that declare a method with an identical signature.

The answer

The answer is that nothing bad happens, as long as the class provides a concrete definition for a method having that signature.

Only one method definition is allowed

Of course, only one definition can be provided for any given method signature, so that definition must satisfy the needs of overriding the inherited method as well as the needs of implementing the interfaces.

An example of signature collisions

The following fragment defines a class named Base that defines a method named test().  The code also defines two interfaces named X and Y, each of which declares a method named test() with an identical signature.
 
class Base{
  public void test(){
    System.out.print("Base ");
  }//end test()
}//end class Base

interface X{
  public void test();
}//end X

interface Y{
  public void test();
}//end Y

class A extends Base implements X,Y{
  public void test(){
    System.out.print("A ");
  }//end test()
}//end class A

Classes A and B extend Base and implement X and Y

The code in the following fragment defines two classes, named A and B, each of which extends Base, and implements both interfaces X and Y.  Each class provides a concrete definition for the method named test(), with each class providing a different definition.
 
class A extends Base implements X,Y{
  public void test(){
    System.out.print("A ");
  }//end test()
}//end class A

class B extends Base implements X,Y{
  public void test(){
    System.out.print("B ");
  }//end test()
}//end class B

Override inherited method and define interface method

Each of the methods named test() in the above fragment serves not only to override the method inherited from the class named Base, but also to satisfy the requirement to define the methods declared in the implemented interfaces named X and Y.

In other words, a single definition of the method in each of the classes serves to satisfy three purposes, one of which is (normally) optional, and the other two of which are required.

Store object's references as type Base and invoke test method

Finally, the code in the following fragment declares a reference variable of the type Base.  Objects respectively of the classes Base, A, and B are instantiated and stored in the reference variable.  Then the method named test() is invoked on each of the references in turn.
 
  void doIt(){
    Base myVar = new Base();
    myVar.test();
    myVar = new A();
    myVar.test();
    myVar = new B();
    myVar.test();
    System.out.println("");
  }//end doIt()
}// end class Worker

As you probably expected, this causes the following text to appear on the screen:

Base A B

Answer 8

C.  A-intfcMethodX B-intfcMethodX

Back to Question 8

Explanation 8

Similar to previous two programs

This program is very similar to the programs in Question 6 and Question 7.  The program is Question 6 exposed a specific type mismatch problem.  The program in Question 7 provided one solution to the problem.

A different solution

The boldface code in the following fragment illustrates a different solution to the problem.
 
  void doIt(){
    X[] myArray = new X[2];
    myArray[0] = new A();
    myArray[1] = new B();
    
    for(int i=0;i<myArray.length;i++){
      myArray[i].intfcMethodX();
    }//end for loop

    System.out.println("");
  }//end doIt()

An array object of the interface type

In this case, rather than to declare the array object to be of type Object, the array is declared to be of the interface type X.

This is a less generic container than the one declared to be of type Object.  Only references to objects instantiated from classes that implement the X interface, or objects instantiated from subclasses of those classes can be stored in the container.  However, this is often adequate.

What methods can be invoked?

Since the references are stored as the interface type, any method declared in the interface can be invoked on the references stored in the container.

(Although it isn't implicitly obvious, it is also possible to invoke any of the eleven methods defined in the Object class on an object's reference being stored as an interface type.)
Not the standard approach

If you are defining your own container, this is a satisfactory approach to implementation of the observer design pattern.  However, you cannot use this approach when using containers from the standard collections framework, because those containers are designed to always store references as the generic type Object.  In those cases, the casting solution of Question 7 is the required.

Answer 7

C.  A-intfcMethodX B-intfcMethodX

Back to Question 7

Explanation 7

The correct use of an interface

This program illustrates the correct use of an interface.  It uses a cast of the interface type in the boldface statement in the following fragment to resolve the problem that was discussed at length in Question 6 earlier.
 
  void doIt(){
    Object[] myArray = new Object[2];
    myArray[0] = new A();
    myArray[1] = new B();
    
    for(int i=0;i<myArray.length;i++){
      ((X)myArray[i]).intfcMethodX();
    }//end for loop

    System.out.println("");
  }//end doIt()

Answer 6

A.  Compiler Error

Back to Question 6

Explanation 6

What is a container?

The word container is often used in Java, with at least two different meaning.  One meaning is to refer to the type of an object that is instantiated from a subclass of the class named Container.  In that case, the object can be considered to be of type Container, and typically appears in a graphical user interface (GUI).  That is not the usage of the word in the explanation of this program.

A more generic meaning

In this explanation, the word container has a more generic meaning.  It is common to store a collection of object references in some sort of Java container, such as an array object or a Vector object.  In fact, there is a complete collections framework provided to facilitate that sort of thing (Vector is one of the concrete classes in the Java Collections Framework).

Storing references at type Object

It is also common to declare the type of references stored in the container to be of the class Object.  Because Object is a completely generic type, this means that a reference to any object instantiated from any class can be stored in the container.  The standard containers such as Vector and Hashtable take this approach.

A class named Base and an interface named X

In a manner similar to several previous programs, this program defines a class named Base and an interface named X as shown in the following fragment.
 
class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

interface X{
  public void intfcMethodX();
}//end X

Classes A and B extend Base and implement X

Also similar to previous programs, this program defines two classes named A and B.  Each of these classes extends the class named Base and implement the interface named X, as shown in the next fragment.
 
class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "A-intfcMethodX ");
  }//end intfcMethodX()
}//end class A

class B extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " B-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "B-intfcMethodX ");
  }//end intfcMethodX()
}//end class B

Concrete definitions of the interface method

As before, these methods provide concrete definitions of the method named intfcMethodX(), which is declared in the interface named X.

An array of references of type Object

The interesting portion of this program begins in the following fragment, which instantiates and populates a two-element array object (container) of type Object(In the sense of this discussion, an array object is a container, albeit a very simple one.)
 
  void doIt(){
    Object[] myArray = new Object[2];
    myArray[0] = new A();
    myArray[1] = new B();

Store object references of type A and B as type Object

Because the container is declared to be of type Object, references to objects instantiated from any class can be stored in the container.  The code in the above fragment instantiates two objects, (one of class A and the other of class B), and stores the two object's references in the container.

Cannot invoke interface method as type Object

The boldface statement in the next fragment produces the following compiler error under JDK 1.3:

Ap136.java:24: cannot resolve symbol
symbol  : method intfcMethodX  ()
location: class java.lang.Object
      myArray[i].intfcMethodX();
 
    for(int i=0;i<myArray.length;i++){
      myArray[i].intfcMethodX();
    }//end for loop

    System.out.println("");
  }//end doIt()

What methods can you invoke as type Object?

It is allowable to store the reference to an object instantiated from any class in a container of the type Object.  However, the only methods that can be directly invoked (without a cast) on that reference are the following eleven methods.  These methods are defined in the class named Object:

Overridden methods

Some, (but not all), of the methods in the above list are defined with default behavior in the Object class, and are meant to be overridden in new classes that you define.  This includes the methods named equals and toString.

Some of the methods in the above list, such as getClass, are simply utility methods, which are not meant to be overridden.

Polymorphic behavior applies

If you invoke one of these methods on an object's reference (being stored as type Object), polymorphic behavior will apply.  The version of the method overridden in, or inherited into, the class from which the object was instantiated will be identified and executed.

Otherwise, a cast is required

In order to invoke any method other than one of the eleven methods in the above list, (on an object's reference being stored as type Object), you must cast the reference to some other type.

Casting to an interface type

The exact manner in which you write the cast will differ from one situation to the next.  In this case, the problem can be resolved by rewriting the program using the interface cast shown in boldface in the following fragment.
 
  void doIt(){
    Object[] myArray = new Object[2];
    myArray[0] = new A();
    myArray[1] = new B();
    
    for(int i=0;i<myArray.length;i++){
      ((X)myArray[i]).intfcMethodX();
    }//end for loop

    System.out.println("");
  }//end doIt()

The observer design pattern

By implementing an interface, and using a cast such as this, you can store references to many different objects, of many different actual types, each of which implements the same interface, but which have no required superclass-subclass relationship, in the same container.  Then, when needed, you can invoke the interface methods on any of the objects whose references are stored in the container.

This is a commonly used design pattern in Java, often referred to as the observer design pattern.

Registration of observers

With this design pattern, none, one, or more observer objects, (which implement a common observer interface) are registered on an observable object.  This means references to the observer objects are stored in a container by the observable object.

Making a callback

When the observable object determines that some interesting event has occurred, the observable object invokes a specific interface method on each of the observer objects whose references are stored in the container.

The observer objects execute whatever behavior they were designed to execute as a result of having been notified of the event.

The model-view-control (MVC) paradigm

In fact, there is a class named Observable and an interface named Observer in the standard Java library.  The purpose of these class and interface definitions is to make it easy to implement the observer design pattern.

(The Observer interface and the Observable class are often used to implement a programming style commonly referred to as the MVC paradigm.)
Delegation event model, bound properties of Beans, etc.

Java also provides other tools for implementing the observer design pattern under more specific circumstances, such as the Delegation Event Model, and in conjunction with bound and constrained properties in JavaBeans Components.

Answer 5

C.  A-intfcMethodX B-intfcMethodX

Back to Question 5

Explanation 5

More substantive use of an interface

This program illustrates a more substantive use of the interface than was the case in the previous programs.

The class named Base

The program defines a class named Base as shown in the following fragment.
 
class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

The interface named X

The program also defines an interface named X as shown in the next fragment.  Note that this interface declares a method named intfcMethodX().
 
interface X{
  public void intfcMethodX();
}//end X

Class A extends Base and implements X

The next fragment shows the definition of a class named A, which extends Base and implements X.
 
class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "A-intfcMethodX ");
  }//end intfcMethodX()
}//end class A

Defining interface method

Because the class named A implements the interface named X, it must provide a concrete definition of all the methods declared in X.

In this case, there is only one such method.  That method is named intfcMethodX().  A concrete definition for the method is provided in the class named A.

Class B also extends Base and implements X

The next fragment shows the definition of another class (named B), which also extends Base and implements X.
 
class B extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " B-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethodX(){
    System.out.print(
                    "B-intfcMethodX ");
  }//end intfcMethodX()
}//end class B

Defining the interface method

Because this class also implements X, it must also provide a concrete definition of the method named intfcMethodX().

Different behavior for interface method

However (and this is extremely important), there is no requirement for this definition of the method to match the definition in the class named A, or to match the definition in any other class that implements X.

Only the method signature is necessarily common among all the classes that implement the interface.

In fact, the definition of the method named intfcMethodX() in the class named A is different from the definition of the method having the same name in the class named B.

The interesting behavior

The interesting behavior of this program is illustrated by the boldface code in the following fragment.
 
  void doIt(){
    X myVar1 = new A();
    myVar1.intfcMethodX();
    X myVar2 = new B();
    myVar2.intfcMethodX();

    System.out.println("");
  }//end doIt()

Store object's references as interface type X

The code in the above fragment causes one object to be instantiated from the class named A, and another object to be instantiated from the class named B.

The references to each of these objects are stored in two different reference variables, each declared to be of the type of the interface X.

Invoke the interface method on each reference

A method named intfcMethodX() is invoked on each of the reference variables.  Despite the fact that both object's references are stored as type X, the system selects and invokes the appropriate method, (as defined by the class from which each object was instantiated), on each of the objects.  This causes the following text to appear on the screen:

A-intfcMethodX B-intfcMethodX

No subclass-superclass relationship exists

Thus, the use of an interface makes it possible to invoke methods having the same signatures on objects instantiated from different classes, without any requirement for a subclass-superclass relationship to exist among the classes involved.

In this case, the only subclass-superclass relationship between the classes named A and B was that they were both subclasses of the same superclass.  Even that relationship was established for convenience, and was not a requirement.

Different behavior of interface methods

The methods having the same signature, (declared in the common interface, and defined in the classes), need not have any similarity in terms of behavior.

A new interface relationship

However, the fact that both classes implemented the interface named X created a new relationship among the classes.  That relationship is not based on class inheritance.

Answer 4

C.  Base A-intfcMethod

Back to Question 4

Explanation 4

Illustrates the use of an interface as a type

The program defines a class named Base, and a class named A, which extends Base, and implements an interface named X, as shown below.
 
class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethod(){
    System.out.print("A-intfcMethod ");
  }//end intfcMethod()
}//end class A

interface X{
  public void intfcMethod();
}//end X

Implementing interfaces

A class may implement none, one, or more interfaces.

The cardinal rule on interfaces

If a class implements one or more interfaces, that class must either be declared abstract, or it must provide concrete definitions of all methods declared in and inherited into all of the interfaces that it implements.  If the class is declared abstract, its subclasses must provide concrete definitions of the interface methods.

A concrete definition of an interface method

The interface named X in this program declares a method named intfcMethod().  The class named A provides a concrete definition of that method.

(The minimum requirement for a concrete definition is a method that matches the method signature and has an empty body.)
Storing object's reference as an interface type

The interesting part of the program is shown in boldface in the following code fragment.
 
  void doIt(){
    Base myVar1 = new Base();
    myVar1.inherMethod();
    X myVar2 = new A();
    myVar2.intfcMethod();

    System.out.println("");
  }//end doIt()

The boldface code in the above fragment instantiates a new object of the class named A, and saves a reference to that object in a reference variable of the declared type X.

How many ways can you save an object's reference?

Recall that a reference to an object can be held by a reference variable whose type matches any of the following:

Save object's reference as implemented interface type

In this program, the type of the reference variable matches the interface named X, which is implemented by the class named A.

What does this allow you to do?

When a reference to an object is held by a reference variable whose type matches an interface implemented by the class from which the object was instantiated, that reference can be used to invoke any method declared in or inherited into that interface.

(That reference cannot be used to invoke methods not declared in or not inherited into that interface.)
In this simple case ...

The method named intfcMethod() is declared in the interface named X and implemented in the class named A.

Therefore, the method named intfcMethod() can be invoked on an object instantiated from the class named A when the reference to the object is held in a reference variable of the interface type.

(The method could also be invoked if the reference is being held in a reference variable of declared type A.)
Invocation of the method causes the text A-intfcMethod to appear on the screen.

Answer 3

C.  Base A-intfcMethod

Back to Question 3

Explanation 3

What is runtime polymorphic behavior?

One way to describe runtime polymorphic behavior is:

The runtime system selects among two or methods having the same signature, not on the basis of the type of the reference variable in which an object's reference is stored, but rather on the basis of the class from which the object was originally instantiated.
Illustrates simple class and interface inheritance

The program defines a class named Base, and a class named A, which extends Base, and implements the interface named X, as shown in the following fragment.
 
class Base{
  public void inherMethod(){
    System.out.print("Base ");
  }//end inherMethod()
}//end class Base

class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethod(){
    System.out.print("A-intfcMethod ");
  }//end intfcMethod()
}//end class A

interface X{
  public void intfcMethod();
}//end X

Define an interface method

The interface named X declares a method named intfcMethod().  A concrete definition of that method is defined in the class named A.

A new object of type Base

The code in the following fragment instantiates a new object of the class Base and invokes its inherMethod().  This causes the word Base to appear on the output.  There is nothing special about this.  This is a simple example of the use of an object's reference to invoke one of its instance methods.
 
  void doIt(){
    Base myVar1 = new Base();
    myVar1.inherMethod();

A new object of type A

The boldface code in the following fragment instantiates a new object of the class A and invokes its intfcMethod().  This causes the test A-intfcMethod to appear on the output screen.  There is also nothing special about this.  This is also a simple example of the use of an object's reference to invoke one of its instance methods.
 
    A myVar2 = new A();
    myVar2.intfcMethod();

    System.out.println("");
  }//end doIt()

Not polymorphic behavior

The fact that the class named A implements the interface named X does not indicate polymorphic behavior in this case.  Rather, this program is an example of simple class and interface inheritance.

Interface type is not used

The program makes no use of the interface as a type, and exhibits no polymorphic behavior (no decision among methods having the same signature is required).

The class named A inherits an abstract method named intfcMethod from the interface and must define it.  (Otherwise, it would be necessary to declare the class named A abstract.)

The interface is not a particularly important player in this program.

Answer 2

A.  Compiler Error

Back to Question 2

Explanation 2

Simple hierarchical polymorphic behavior

This program is designed to test your knowledge of simple hierarchical polymorphic behavior.

Implement the interface named X

This program defines a class named A that extends a class named Base, and implements an interface named X, as shown in the following code fragment.
 
class A extends Base implements X{
  public void inherMethod(){
    System.out.print(
                    " A-inherMethod ");
  }//end inherMethod()
    
  public void intfcMethod(){
    System.out.print("A-intfcMethod ");
  }//end intfcMethod()
}//end class A

interface X{
  public void intfcMethod();
}//end X

Override and define some methods

The class named A overrides the method named inherMethod(), which it inherits from the class named Base.  It also provides a concrete definition of the method named intfcMethod(), which is declared in the interface named X.

Store object's reference as superclass type

The program instantiates an object of the class named A and assigns that object's reference to a reference variable of type Base, as shown in the following code fragment.
 
    Base myVar2 = new A();

Oops!  Cannot invoke this method

So far, so good.  However, the next fragment shows where the program turns sour.  It attempts to invoke the method named intfcMethod() on the object's reference, which was stored as type Base.
 
    myVar2.intfcMethod();

Polymorphic behavior doesn't apply here

Because the class named Base does not define the method named intfcMethod(), hierarchical polymorphic behavior does not apply.  Therefore a reference to the object being stored as type Base cannot be used to directly invoke the method named intfcMethod(), and the program produces a compiler error.

What is the solution?

Hierarchical polymorphic behavior is possible only when the class defining the type of the reference (or some superclass of that class) contains a definition for the method that is invoked on the reference.

There are a couple of ways that downcasting could be used to solve the problem in this case.

Answer 1

A.  Compiler Error

Back to Question 1

Explanation 1

I put this question in here just to see if you are still awake.

Can store reference as interface type

A reference to an object instantiated from a class can be assigned to any reference variable whose declared type is the name of an interface implemented by the class from which the object was instantiated,  or implemented by any superclass of that class.

Define two classes and an interface

This program defines a class named A that extends a class named Base.  The class named Base extends Object by default.

The program also defines an interface named X.

Instantiate an object

The following statement instantiates an object of the class named A, and attempts to assign that object's reference to a reference variable whose type is the interface type named X.
 
    X myVar2 = new A();

Interface X is defined but not implemented

Neither the class named A, the class named Base, nor the class named Object implements the interface named X.  Therefore, it is not allowable to assign a reference to an object of the class named A to a reference variable whose declared type is X.  Thus, the program produces the following compiler error under JDK 1.3:

Ap131.java:20: incompatible types
found   : A
required: X
    X myVar2 = new A();



Copyright 2002, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java and XML. In addition to the many platform-independent benefits of Java applications, he believes that a combination of Java and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects involving Java, XML, or a combination of the two.  He frequently provides onsite Java and/or XML training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Java Programming Tutorials, which has gained a worldwide following among experienced and aspiring Java programmers. He has also published articles on Java Programming in Java Pro magazine.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

baldwin.richard@iname.com

-end-