RoboDuke's School of Java - Lesson 6, Chapter 7

In this lesson we are going to look at inheritance. But first I will tell you a joke from the Robot Kingdom about inheritance. Takes a while but well worth it in the end.

Toaster meets Software developer
Once upon a time, in a kingdom not far from here, a king summoned two of his advisors for a test. He showed them both a shiny metal box with two slots in the top, a control knob, and a lever. "What do you think this is?" One advisor, an Electrical Engineer, answered first. "It is a toaster," he said. The king asked, "How would you design an embedded computer for it?" The advisor: "Using a four-bit microcontroller, I would write a simple program that reads the darkness knob and quantifies its position to one of 16 shades of darkness, from snow white to coal black. The program would use that darkness level as the index to a 16-element table of initial timer values. Then it would turn on the heating elements and start the timer with the initial value selected from the table. At the end of the time delay, it would turn off the heat and pop up the toast. Come back next week, and I'll show you a working prototype."

The second advisor, a software developer, immediately recognized the danger of such short-sighted thinking. He said, "Toasters don't just turn bread into toast, they are also used to warm frozen waffles. What you see before you is really a breakfast food cooker. As the subjects of your kingdom become more sophisticated, they will demand more capabilities. They will need a breakfast food cooker that can also cook sausage, fry bacon, and make scrambled eggs. A toaster that only makes toast will soon be obsolete. If we don't look to the future, we will have to completely redesign the toaster in just a few years." "With this in mind, we can formulate a more intelligent solution to the problem.

First, create a class of breakfast foods. Specialize this class into subclasses: grains, pork, and poultry. The specialization process should be repeated with grains divided into toast, muffins, pancakes, and waffles; pork divided into sausage, links, and bacon; and poultry divided into scrambled eggs, hard-boiled eggs, poached eggs, fried eggs, and various omelet classes."

"The ham and cheese omelet class is worth special attention because it must inherit characteristics from the pork, dairy, and poultry classes. Thus, we see that the problem cannot be properly solved without multiple inheritance. At run time, the program must create the proper object and send a message to the object that says, 'Cook yourself.' The semantics of this message depend, of course, on the kind of object, so they have a different meaning to a piece of toast than to scrambled eggs."

"Reviewing the process so far, we see that the analysis phase has revealed that the primary requirement is to cook any kind of breakfast food. In the design phase, we have discovered some derived requirements. Specifically, we need an object-oriented language with multiple inheritance. Of course, users don't want the eggs to get cold while the bacon is frying, so concurrent processing is required, too."

"We must not forget the user interface. The lever that lowers the food lacks versatility, and the darkness knob is confusing. Users won't buy the product unless it has a user-friendly, graphical interface. When the breakfast cooker is plugged in, users should see a cowboy boot on the screen. Users click on it, and the message 'Booting UNIX v.8.3' appears on the screen. (UNIX 8.3 should be out by the time the product gets to the market.) Users can pull down a menu and click on the foods they want to cook."

"Having made the wise decision of specifying the software first in the design phase, all that remains is to pick an adequate hardware platform for the implementation phase. An Intel Pentium with 48MB of memory, a 1.2GB hard disk, and a SVGA monitor should be sufficient. If you select a multitasking, object oriented language that supports multiple inheritance and has a built-in GUI, writing the program will be a snap."

The king wisely had the software developer beheaded, and they all lived happily ever after.

After that, you will find Java inheritance concepts a snap – easy but robust!

Now --- on to our lesson! Download our jar file for lesson 6 from the link below:

Let’s look at the programs you were to write in lesson 5. The main goal was to become familiar with reading APIs – both created for Sun Java classes and ones written by the programmer. The code, located in the answerslesson5 package is pretty straight-forward (I promise to challenge you more in this lesson) so I will let you just look at these (I am excited to get on with the inheritance thing so I can make a robot-toaster!). Post any questions that you might have to the discussion forum.

Chapter 7 in your text discusses inheritance and how and why we use it. Watch the movies as you read through this assignment. You will find them at
http://www.vw.vccs.edu/bussci/Wolff/robot/lesson6Inheritance/lesson6Inheritan... and
http://www.vw.vccs.edu/bussci/Wolff/robot/lesson6driver/lesson6driver.html

In a nutshell, we use inheritance to avoid duplication of code and to share functionality between related classes. Often there are a large number of these classes, so we will utilize a UML (Unified Modeling Language) to diagram the relationship and contents of the classes. UML is not a Java thing – it is utilized in most languages today to model relationships (there are actually over a dozen different diagrams you can use --- we will look at only one called the class diagram. There is a tool named Omondo that we added as a plug-in for Eclipse that draws these diagrams. Here is the one that we are going to look at in this lesson. First let’s look at the classes themselves.

a. Customer – a blueprint for a customer who buys insurance.
Note that the colored icon in front is an indication of the access modifier. The red square indicates that the instance variable is private. The red S means static and the green circle means public. The green C means a constructor. Note that this diagram tells you everything that you need to know about writing the class!

b. Insurance - the super class. The generic class that we will use for inheritance.

c. The other four are subclasses. These are ArtInsurance, HealthInsurance, LifeInsurance, and AutoInsurance. The way you make these subclasses is to have their class definition similar to

public class AutoInsurance extends Insurance {

The word extends means inheritance. But what is actually inherited? (I am so glad that you asked your robot friend!!). Anything that is not private. The access modifier private means that it belongs only to that class and no one else (including inherited classes) can get to it. You will note that we changed the access modifiers on the Insurance instance variables to protected which means that classes that inherit from this class will inherit the instance variables. Since the methods are public, the subclass gets these as well. So, in a robot-shell, all instance variables and methods that are not private are inherited by just saying extends Superclass (except the constructors and that is another story).

How powerful is that? AutoInsurance can now use all of the instance variables and methods both in its class and in the Insurance class.

d. You can look at the actual code to see the details but below is a diagram of the relationship of the six classes.

Note that the Insurance class has a field that is of Customer type. This is a has-a relationship or association since you would say that “Insurance has a Customer”. That is NOT inheritance, but is called association.

The relationship between Insurance and the other four classes is called an is-a relationship since “AutoInsurance is-a Insurance” and “HealthInsurance is-a Insurance”, etc. This is inheritance.

When creating classes in an inheritance hierarchy like this, one overriding rule is to move common things as far up the inheritance chain as possible and let the instance variables be handled by the class where they are defined. But what does that mean?

The Insurance class has instance variables representing three things: the customer, policy number, and yearly rate. Since all types of insurance will have these three attributes, they are defined in the Insurance class. It is wrong to move them to the other classes since you would need them in all four classes and that duplicates code. Hence – move common things as far up the inheritance chain as possible.

Now let’s look at the various toString() methods. The one in the Customer class looks like:

public String toString()
{
return first + " " + last +",Id=" + id;
}

Nothing new here. The one in the Insurance class is a little different than we wrote in our previous lessons. Here is the code:

public String toString ()
{
return (customer.toString() + " with policy number " + policyNumber + " has a yearly rate of " + currency.format(yearlyRate));
}

Note that the customer object’s toString() method was called to print out its instance variables and the rest of this method (which is in the Insurance class) is used to write out the Insurance instance variables. Hence - let the instance variables be handled by the class where they are defined. Let’s look at another example of that.

The AutoInsurance toString() method looks like

public String toString ()
{
String ans = super.toString();
return ans + (" for auto insurance. The number of cars are " + numCars + ".");
}

Note that the first line is a call to super.toString(). We are in the AutoInsurance class so super is the Insurance class. Hence – the Insurance class writes out its information (which also allows the customer that is in there to write out their information) and then the AutoInsurance class writes out its fields.

We said that a subclass inherits all things that are not private (except constructors) from the superclass. But what if the subclass has a method with an identical signature to the superclass? Think about it. That is what is happening with the toString() method. This is called overriding and in this case the method in the subclass overrides the one that is inherited and will therefore use its own version of the method.

What if you wanted to use the version of the method that is in the super class? We saw that in the toString() method. The first line in the AutoInsurance toString method was a call to super.toString() which calls the version from the super class. To override, the signature of the method needs to be identical. Look at pages 165-170 in your text.

Now study the code for our application and read the comments carefully. You will see that we carefully avoid duplication of code and we put methods and instance variables in the classes where they are the most appropriate. Note that each of the four subclasses has a calcRate() method. This may seem like duplication of code, but it is not since the way you calculate the cost of insurance is totally different for cars than for health then for art or life. So each class needs its own calcRate() method. Actually every type of insurance should be forced to have a calcRate() method (so the RoboInsurance agent can get their commissions). We will see how to make this happen in the next lesson.

Unlike some other languages, a class can only have one super class (single parent robot families) and there is an ultimate top class we will discuss in Chapter 8 called Object. However, you can have more than one subclass for a super class. Look at the diagram below as one possible example.

A class can have just one parent but a class can have one or more subclasses. It just depends on the application that you are trying to solve.

So the burning question in your mind is “when should I use this inheritance design pattern?” The answer is that it is not appropriate in every case. See page 181 in your text. To use inheritance, there should be a real is-a relationship between the classes. And what does it buy you? See pages 182-183 in your text. Skim pages 184-189 for the moment – we will be back to these in the next lesson.

Study the code in the example. Then look at the driver program which will create objects from the classes and store them in ArrayLists. For the inheritance chain, we will create an ArrayList as

ArrayList ins = new ArrayList();

Since we have the is-a relationship, this can be used to store all five types of insurance all in this one ArrayList. Under the covers, Java knows which type of Insurance it really is and when you call the toString() method on one of the objects, Java has the ability to call the method from the correct class. More on that in the next chapter.

The program will run from a set of menu choices. Go through the code for each method choice and read the comments. Make certain that you understand the logic for each. Watch the movie at http://www.vw.vccs.edu/bussci/Wolff/robotinheritance//inheritance.html for explanations of the code.

RoboDuke’s Extra Extra Strength Challenge

Get the document at http://www.vw.vccs.edu/bussci/Wolff/robot/InventoryProject.doc and follow the directions to see if you can create RoboDuke’s Pet Store using the concepts in this module. Send your answer to dwolff@vw.vccs.edu and impress her. Tell her RoboDuke sent you!!! She will post the best answers and you can become famous!!!