Java The Essence of OOP Using Java, Inheritance, Part 1

The Essence of OOP Using Java, Inheritance, Part 1

Java Programming Notes #1604


Preface


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

The first lesson in the group was entitled
The
Essence of OOP Using Java, Objects, and Encapsulation
.  That lesson,
and each of the lessons following that one, has provided explanations of
certain aspects of the essence of Object-Oriented Programming using Java.  
The previous lesson was entitled
The Essence of
OOP using Java, Classes
.

Essence

My dictionary provides several definitions for the word essence. 
Among those definitions are the following:

  • The property necessary to the nature of a thing
  • The most significant property of a thing

Thus, this miniseries will describe and discuss the necessary and
significant
aspects of OOP using Java.

I will attempt to provide that information in a high-level format, devoid
of any requirement to understand detailed Java syntax.  In those cases
where an understanding of Java syntax is required, I will attempt to provide
the necessary syntax information in the form of sidebars or other obvious
formats.

Therefore, if you have a general understanding of computer programming,
you should be able to read and understand the lessons in this miniseries,
even if you don’t have a strong background in the Java programming language.

Viewing tip

You may find it useful to open another copy of this lesson in a separate
browser window.  That will make it easier for you to scroll back and
forth among the different listings while you are reading about them.

Supplementary material

I recommend that you also study the other lessons in my extensive collection
of online Java tutorials.  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
.

Preview


Extending a class

This lesson shows you how to extend an existing class to create a new
class.  The new class is the blueprint for a new type.

Inheritance and code reuse

The existing class is often called the superclass and the new
class is often called the subclass.  This is the mechanism
for class inheritance in Java.  Inheritance provides a formal
mechanism for code reuse.

The subclass inherits all of the variables and all of the methods defined
in the superclass.

Car radios with tape players

A class from a previous lesson (whose objects represent car radios)
is extended to define a new class, whose objects represent expanded car
radios that contain tape players.

Sending messages to the object

Objects of the new class know how to respond to messages for inserting,
playing, and removing a tape, in addition to those messages appropriate
for objects of the original Radio class.

Discussion
and Sample Code


The three pillars of OOP

In an earlier lesson, I explained that most books on OOP will tell you
that in order to understand OOP, you must understand the following three
concepts:

  • Encapsulation
  • Inheritance
  • Polymorphism

I agree with that assessment.

Encapsulation

The first lesson in this series provided an explanation of encapsulation.

Inheritance

This lesson will provide an explanation of inheritance
I will use another simple program to explain the concept of inheritance.

Polymorphism

Polymorphism is the most complex of the three, and will be explained
in future lessons.

A new data type

Whenever you define a class in Java, you cause a new data type to become
available to the program.  Therefore, whenever you need a new data
type, you can define a new class to make that type available.

Extending a class

Defining a new class (to create a new type) can involve a lot
of effort.  Sometimes you have an option that can greatly reduce the
effort required to create your new type.  If a class (type)
already exists that is close to what you need, you can often extend
that class to produce a new class that is closer to what you need. 
In many cases, this will require much less effort than that required to
start from scratch and define a new class to establish a new type.

The ability to extend one class into another new class is the essence
of inheritance.

According to the current jargon, the new class is called the subclass
and
the class that was extended is called the superclass.

What is inherited?

The subclass inherits all of the variables and all of the methods defined
in (or inherited into) the superclass, almost as if you had completely
defined the new class from scratch, and had reproduced all of the code
already defined in the existing superclasses.

Code reuse

Therefore, inheritance often makes it possible to define a new class
with a minimum requirement to write new code by formally reusing the code
that was previously written into the superclasses.

Sometimes you can get by with simply extending the existing class. 
Sometimes, however, it is necessary to make changes to the existing class
to improve its ability to be extended in a meaningful way.  (That
is the case with the sample program discussed in this lesson, but the next
lesson will show you how to avoid that problem.)
  It all depends
on how the existing class was designed in the first place.

The Radio class

A previous program defined a class named Radio.  Objects
instantiated from the Radio class (see the previous lessons for
a discussion of instantiating objects)
were intended to simulate car
radios. (Note that the car radios simulated by objects of the Radio
class didn’t have built-in tape players.)

The Combo class

In this lesson, I will use inheritance to extend the Radio class
into a new class named Combo.  Objects instantiated from the
Combo
class are intended to simulate car radios with a built-in tape player.

A complete listing of the new program is shown in Listing 9 near the
end of the lesson.

Will discuss in fragments

As usual, I will discuss this program in fragments.  I will begin
my discussion with the definition of the new class named Combo
Then I will come back and discuss the class named Radio and the
driver class named Radio02.

The combo class

The code in Listing 1 shows the beginning of the class named Combo.
(Note
that the boldface was added for emphasis only.  Java source code does
not use boldface, Italics, or other such typographical features.)


 

class Combo extends Radio{
  
  public Combo(){//constructor
    System.out.println(
           "Combo object constructed");
  }//end constructor

Listing 1

Two new items

There are two new items in Listing 1 that you did not see in the code
in the previous lesson.

Combo extends Radio

First, the class named Combo extends the class named Radio
This means that an object instantiated from the Combo class will
contain all of the variables and all the methods defined in the Combo
class, plus all the variables and methods defined in the Radio class,
and its superclasses.
(The variables and methods of the superclass are
inherited into the subclass.)

An explicit constructor

Second, the class named Combo defines an explicit constructor.

Defining a constructor is optional

When defining a new class, it is not necessary to define a constructor. 
If you don’t define a constructor, a default constructor will be provided
automatically.

Why define a constructor?

The intended purpose of a constructor is to initialize the instance
variables belonging to the new object.  However, constructors can
do other things as well.  In this case, I used an explicit constructor
to display a message when the object is instantiated from the class named
Combo.

Brief discussion of constructors

I’m not going to discuss constructors in detail at this point. 
However, I will give you a few rules regarding constructors.

  • Constructors (like methods) can be overloaded (I will explain
    what overloading means in a subsequent lesson).
  • The names of constructors must match the names of the classes in which
    they are defined.
  • A constructor signature never indicates a return type (such as void).
  • The code in a constructor never contains a return statement.

Instance methods

The new class named Combo defines three instance methods, each
of which has to do with the handling of tape in the tape player:

  • insertTape
  • removeTape
  • playTape

(If you feel ambitious, you could upgrade this class even further to
add features such as rewind, fast forward, pause, etc.).

The insertTape method

The entire method named insertTape is shown in Listing 2. 
This is the method that is used to simulate the insertion of a tape by
the user.

 

  public void insertTape(){
    System.out.println("Insert Tape");
    tapeIn = true;
    System.out.println("  Tape is in");
    System.out.println(
                     "  Radio is off");
  }//end insertTape method

Listing 2

The most significant thing about the code in Listing 2 is the assignment
of the true value to the boolean variable named tapeIn
Other than setting the value of the tapeIn variable to true,
the code in Listing 2 simply prints some messages to indicate what is going
on.

What is tapeIn used for?

As you will see shortly, the value of the variable named tapeIn
is used to determine if it is possible to play the tape or to play the
radio.

According to that logic:

  • If tapeIn is true, it is possible to play the tape but it is not
    possible to play the radio.
  • If tapeIn is false, it is possible to play the radio, but it is
    not possible to play the tape.

tapeIn is not declared in the Combo class

It is also worthy of note that in this version of the program, the variable
named tapeIn is not declared in the Combo class (this
will change in the next lesson where the program uses method overriding).
 
Rather, this variable is inherited from the Radio class that is
extended by the Combo class.

The removeTape method

The removeTape method of the Combo class is shown in Listing
3.  Its behavior is pretty much the reverse of the insertTape
method, so I won’t discuss it further.

 

  public void removeTape(){
    System.out.println("Remove Tape");
    tapeIn = false;
    System.out.println(
                      "  Tape is out");
    System.out.println(
                      "  Radio is on");
  }//end removeTape method

Listing 3

The playTape method

Listing 4 shows the method named playTape defined in the new
Combo
class.

 

  public void playTape(){
    System.out.println("Play Tape");
    if(!tapeIn){//tapeIn is false
      System.out.println(
            "  Insert the tape first");
    }else{//tapeIn is true
      System.out.println(
                  "  Tape is playing");
    }//end if/else
  }//end playTape

Listing 4

Confirm that the tape is ready

The invocation of the method named playTape can be thought of
as sending a message to the Combo object to play the tape. 
The code in the playTape method checks to confirm that the value
stored in the tapeIn variable is true before implementing
the incoming message to play the tape.

If tapeIn is false, an error message is displayed advising the
user to insert the tape first.

If tapeIn is true, the method prints a message indicating that
the tape is playing.

Modified Radio class

Listing 5 shows the definition of the modified version of the class
named Radio.  The significant changes that were made to this
class are shown in boldface (a couple of other changes were made simply
to print some information indicating what is going on while the program
is executing).


 

class Radio{
  protected double[] stationNumber = 
                         new double[5];
  protected boolean tapeIn = false;
  //---------------------------------//
  
  public void setStationNumber(
                int index,double freq){
    stationNumber[index] = freq;
    System.out.println("Button " 
              + index + " programmed");
  }//end method setStationNumber
  //---------------------------------//
  
  public void playStation(int index){
    System.out.println("Play Radio");
    if(!tapeIn){//tapeIn is false
      System.out.println(
          "  Playing the station at " 
               + stationNumber[index]
               + " Mhz");
    }else{//tapeIn is true
      System.out.println(
            "  Remove the tape first");
    }//end if/else
  }//end method playStation
  
}//end class Radio

Listing 5

Tape status

The first significant change that was made to the class named Radio
is shown in Listing 6 below.

 

  protected boolean tapeIn = false;

Listing 6

The statement in Listing 6 declares and initializes a new instance variable
named
tapeIn.  As explained earlier, this instance variable
is used to indicate whether or not a tape is inserted.  (The Combo
class inherits this variable.)

Earlier in this lesson, I explained how the playTape method of
the Combo class uses this value to determine whether or not to attempt
to play a tape.

Change to the playStation method

The significant change that was made to the method named playStation
of the
Radio class is shown by the boldface code in Listing 7 below.

 

    if(!tapeIn){//tapeIn is false
      System.out.println(
          "  Playing the station at " 
               + stationNumber[index]
               + " Mhz");
    }else{//tapeIn is true
      System.out.println(
            "  Remove the tape first");
    }//end if/else

Listing 7

Check the tape status

The code in Listing 7 uses tapeIn to check the tape status before
attempting to tune the radio station and play the radio.  If a tape
is inserted, this method simply displays an error message instructing the
user to remove the tape first.

So, what’s the big deal with inheritance?

The fact that it was necessary for me to make changes to the class named
Radio
greatly reduced the benefit of inheritance in this case.  However,
even in this case, the use of inheritance eliminated the need for me to
define a new class that reproduces all of the code in the class named Radio.

(In the next lesson, I will explain the process of overriding methods. 
I will show you how to use method overriding to accomplish these same purposes
by extending the Radio class, without any requirement to modify the code
in the Radio class.  That will be a much better illustration of the
benefits of inheritance.)

The driver class

The new driver class named Radio02 is shown in Listing 8.

 

public class Radio02{
  //This class simulates the 
  // manufacturer and the human user
  public static void main(
                        String[] args){
    Combo myObjRef = new Combo();
    myObjRef.setStationNumber(3,93.5);
    myObjRef.playStation(3);
    myObjRef.insertTape();
    myObjRef.playStation(3);
    myObjRef.removeTape();
    myObjRef.playStation(3);
    myObjRef.playTape();
    myObjRef.insertTape();
    myObjRef.playTape();
    myObjRef.removeTape();
    myObjRef.playStation(3);
  }//end main
}//end class Radio02

Listing 8

New object of the Combo class

The most significant change in this class (relative to the driver
class named Radio01 in a previous lesson)
is the single statement in
boldface.  Note that unlike the previous program, this program instantiates
a new object of the Combo class (instead of the Radio class).

All of the other new code in Listing 8 is used to send messages to the
new object in order to exercise its behavior.

Program output

That object responds to those messages by producing the following output
on the computer screen:

Combo object constructed

Button 3 programmed

Play Radio

  Playing the station at 93.5 Mhz

Insert Tape

  Tape is in

  Radio is off

Play Radio

  Remove the tape first

Remove Tape

  Tape is out

  Radio is on

Play Radio

  Playing the station at 93.5 Mhz

Play Tape

  Insert the tape first

Insert Tape

  Tape is in

  Radio is off

Play Tape

  Tape is playing

Remove Tape

  Tape is out

  Radio is on

Play Radio

  Playing the station at 93.5 Mhz

Leave as an exercise for the student

As the old saying goes, I will leave it as an exercise for the student
to correlate the messages in Listing 8 with the output shown above.

Summary


Extending an existing class often provides an easy way to create a new
type.  This is primarily true when an existing class creates a type
whose features are close to, but not identical to the features needed in
the new type.

When an existing class is extended to define a new class, the existing
class is often called the superclass and the new class is often
called the subclass.

The subclass inherits all of the variables and all of the methods defined
in the superclass and its superclasses.

Inheritance provides a formal mechanism for code reuse.

This lesson modifies slightly, and then extends the Radio class
from a previous lesson to define a new class named Combo
Objects of the Combo class simulate car radios that contain tape
players.  Objects of the Combo class know how to respond to
messages for inserting, playing, and removing a tape, in addition to those
messages appropriate for an object of the Radio class.

The changes that were required in the definition of the Radio
class provide for the fact that it is not possible to play a radio station
and to play a tape at the same time.  This change was necessary because
the original designer of the Radio class (this author) didn’t
design that class with the idea of extending it to include a tape player. 
This points out the importance of thinking ahead when defining a new class.

What’s Next?


In the next lesson, I will show you how to use method overriding
to cause the behavior of a method inherited into a subclass to be appropriate
for an object instantiated from the subclass.  I will also show you
how to use method overriding to eliminate the above requirement to modify
the Radio class before extending it.

Complete Program Listing


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

The primary difference between this program and the program in the earlier
lesson (whose objects simulate car radios) is the inclusion in this
program of a new class named Combo.  The class named Combo
extends the original Radio class to create a new type of radio that
also contains a tape player.

 

/*File Radio02.java
Copyright 2002, R.G.Baldwin
Simulates the manufacture and use of a 
combination car radio and tape player.

This program produces the following
output on the computer screen:
  
Combo object constructed
Button 3 programmed
Play Radio
  Playing the station at 93.5 Mhz
Insert Tape
  Tape is in
  Radio is off
Play Radio
  Remove the tape first
Remove Tape
  Tape is out
  Radio is on
Play Radio
  Playing the station at 93.5 Mhz
Play Tape
  Insert the tape first
Insert Tape
  Tape is in
  Radio is off
Play Tape
  Tape is playing
Remove Tape
  Tape is out
  Radio is on
Play Radio
  Playing the station at 93.5 Mhz
**************************************/

public class Radio02{
  //This class simulates the 
  // manufacturer and the human user
  public static void main(
                        String[] args){
    Combo myObjRef = new Combo();
    myObjRef.setStationNumber(3,93.5);
    myObjRef.playStation(3);
    myObjRef.insertTape();
    myObjRef.playStation(3);
    myObjRef.removeTape();
    myObjRef.playStation(3);
    myObjRef.playTape();
    myObjRef.insertTape();
    myObjRef.playTape();
    myObjRef.removeTape();
    myObjRef.playStation(3);
  }//end main
}//end class Radio02
//===================================//

class Radio{
  //This class simulates the plans from
  // which the radio object is created.
  protected double[] stationNumber = 
                         new double[5];
  protected boolean tapeIn = false;
  //---------------------------------//
  
  public void setStationNumber(
                int index,double freq){
    stationNumber[index] = freq;
    System.out.println("Button " 
              + index + " programmed");
  }//end method setStationNumber
  //---------------------------------//
  
  public void playStation(int index){
    System.out.println("Play Radio");
    if(!tapeIn){
      System.out.println(
          "  Playing the station at " 
               + stationNumber[index]
               + " Mhz");
    }else{
      System.out.println(
            "  Remove the tape first");
    }//end if/else
  }//end method playStation
  
}//end class Radio
//===================================//

class Combo extends Radio{
  
  public Combo(){//constructor
    System.out.println(
           "Combo object constructed");
  }//end constructor
  //---------------------------------//
  
  public void insertTape(){
    System.out.println("Insert Tape");
    tapeIn = true;
    System.out.println("  Tape is in");
    System.out.println(
                     "  Radio is off");
  }//end insertTape method
  //---------------------------------//
  
  public void removeTape(){
    System.out.println("Remove Tape");
    tapeIn = false;
    System.out.println(
                      "  Tape is out");
    System.out.println(
                      "  Radio is on");
  }//end removeTape method
  //---------------------------------//
  
  public void playTape(){
    System.out.println("Play Tape");
    if(!tapeIn){
      System.out.println(
            "  Insert the tape first");
    }else{
      System.out.println(
                  "  Tape is playing");
    }//end if/else
  }//end playTape
}//end class combo

Listing 9

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.

[email protected]

Latest Posts

Related Stories