Incremental Java
Inheritance

What is OOP?

What is object oriented programming (OOP)? Right now, you've learned how to write a simple class definition, and write a test class so you can experiment with objects. Is that object-oriented programming? Programming with objects?

Most programmers say OOP includes the following:

Inheritance is the only concept we haven't talked about.

Classification

Scientists have often classified nature. For example, we say that something is animal. A mammal is a kind of animal. Humans are a kind of animal.

We can think of these as sets. Animal is a large set. Mammal is a subset inside this set. Humans are subsets of mammals.

There are relationships between classes too. We'll explore these relationships.

Class Extension

Suppose you want to use a Rectangle class. However, the problem with the class is that you can't specify a color. You want to draw blue rectangles or red rectangles, and so forth. You could write a ColorRectangle class, and rewrite the code for Rectangle again.

But wouldn't it be nice if we could reuse the code from Rectangle and just add the new information? You can!

Here's how:

public class ColorRectangle extends Rectangle
{
   Color color ;
   public ColorRectangle()
   {
      color = Color.RED ;
   }

   public ColorRectangle( int initWidth, int initHeight, Color initColor )
   {
      super( initWidth, initHeight ) ;
      color = initColor ;
   }
   
   public void setColor( Color inColor )
   {
      color = inColor ;
   }

   public Color getColor()
   {
      return color ;
   }
}
By using the keyword extends Rectangle, Java does the following for us: Notice that we do not recopy the methods from Rectangle into ColorRectangle. Thus, to know what methods a ColorRectangle object can react to, we are forced to look at the public methods Rectangle since tose are inherited.

Derived Class

We used inheritance to create ColorRectangle from Rectangle. We also say that ColorRectangle is derived from Rectangle.

Parent/Child Class

We also say that Rectangle is a parent class and ColorRectangle is a child class.

We can even extend ColorRectangle to ColorRectangle3D. In this case, we say ColorRectangle3D is a descendant class of Rectangle (and for convenience, we also say it is a descendant class of its parent class).

Similary, Rectangle is an ancestor class for ColorRectangle3D (and ColorRectangle).

Restrictions on Accessing Private Instance Variables

There is one big restriction with inheritance. Even though ColorRectangle contains instance variables from Rectangle (plus any additional instance variables that were declared specifically in ColorRectangle), you can't directly access the instance variables from Rectangle.

For example, suppose you are writing method definitions for some new method in ColorRectangle. You can't use this.height or this.width directly, even though both instance variables are part of the instance variables of ColorRectangle (inherited from Rectangle).

In other words, a child class can't access the private instance variables inherited from the parent class.

The following is incorrect:

public class ColorRectangle
{
   // Method in ColorRectangle, but not in Rectangle
   public void doubleWidth()
   {
      // INVALID! Can't access width!
      width = 2 * width ;  
   }
}
Does this seem strange? You inherited instance variables from the parent class? What can't you access it? It's like inheriting money from someone, without being able to spend it. (Well, not exactly).

The reason is encapsulation. The designers of Java (and similar object oriented languages) assume that you do not write all classes.

In particular, suppose someone else wrote the Rectangle class. This class designer wants to make a new version of Rectangle, but the only changes they make are internal changes, changes that are hidden from the object user.

They change the names of the instance variables from height and width to h and w.

Suppose you had already written some code in ColorRectangle and you could access this.height and this.width directly. Your code would fail to compile when the new version of Rectangle was released.

Since you can't access private instance variables inherited from the parent class, any internal changes to Rectangle should not force you to change the code in ColorRectangle.

Still, this seems like a huge problem. What if you need to modify instance variables inherited from the parent class? What if you want to write a doubleWidth() method? How do you do it? You do it like the object user! You use public methods! With setWidth() and getWidth(), you can read and modify the width.

So here's how you'd write doubleWidth().

public class ColorRectangle
{
   // Method in ColorRectangle, but not in Rectangle
   public void doubleWidth()
   {
      // OK! Uses setWidth() and getWidth() from Rectangle
      setWidth( 2 * getWidth() ) ;
   }
}
Remember, we're allowed to use public methods from the parent class. Thus, getWidth() and setWidth() are valid. We aren't allowed to use anything private from the parent class (including private methods).

You might ask "But, what if the person changes the methods of Rectangle?"

Public Methods are Sacred

When you write a class and publish the public methods, you are essentially telling anyone who uses your class "I promise not to change the public methods in the future".

Why would you make such a promise?

The reason is that anyone who uses your class is going to have to rewrite their code if you change the methods. Rewriting code can be painful to everyone who uses your class, so it's generally best to avoid changing public methods.

Having said that, it does happen from time to time. Java has classes where some of the methods that are deprecated, which means it still exists, but you're recommended to not use them because they may disappear in future versions of Java (Java is always coming out with new versions that change things here and there).

Extending a Class

When you use inheritance, as we did for extending ColorRectangle from Rectangle, you can make one of several changes. We call Rectangle the parent class (or the ancestor class) and ColorRectangle the child class (or the descendant class). You also hear superclass and base class instead of parent class, and subclass and derived class instead of child class.

Notice that you can't remove any methods or instance variables. This is an important feature of inheritance. We'll see why soon.