next up previous
Next: Week 11 Up: Week 10 Previous: Vector class

Inheritance

In the last section we mentioned that the Vector actually stores references to objects of type Object, and that it can store a reference to any type of object because of inheritance. But what does this mean?

In the same manner that a child inherits attributes of her parents, we can have child classes which inherit the attributes of their parent class. That is, if we explicitly say 'my new class is a child of such and such a class' then our new class will 'get' the methods and variables of the parent class, in addition to whatever new methods and variables we decide to add.

It's just as if we were to write our new class and cut and paste all the methods and variables from the 'parent' class and put them in our new class. Well, not quite. We don't get the constructor from the parent, and we'll still have to observe our 'visibility' rules: private variables and methods of the parent class will not be visible in the child class, even though the child does, in some sense, inherit them. Let's explain this a little more carefully.

First of all the way we say 'my new class is a child of such and such a class' is by using the Java keyword extends. For example, let's create a class Person and a child or subclass Student.


class Person{
    private String name;
    public String getName(){ return name;}
}

class Student extends Person{

    private int snum;
    public int getSnum(){ return snum; }
}

Now, what happens if we instantiate a Student object? The statement looks as we would expect:


Student s1 = new Student();

and the object looks like:

Figure 28: Memory model showing Student object
\begin{figure}
\begin{center}
\epsfxsize =5in {\epsfbox {inherit1.ps}} \\
\end{center}\end{figure}

Note that a single object has two parts to it! As you can see, each object of a class which is a child or subclass carries information about its parent or superclass. However, we can't access name from any of the methods defined in Person because name is private. Thus, although storage for the variable name is allocated when we instantiate a Student object, we can't access it directly (only because it's private; a public variable would be accessible). On the other hand, since the method getName() is public, we can access getName() from within methods of the Person class.

We can, however do the following, for example:


System.out.println(s1.getSnum());
System.out.println(s1.getName());

What the compiler/virtual machine does in this circumstance is to look up the s1 object, and run the appropriate method, just as if the object didn't have parts. However, never forget that because the object has more than one part, the keywords public and private perform there function as if the two parts were different classes.

Now what we've just said is actually not entirely correct -- the situation is slightly more complicated. It turns out that there is one special class which is a superclass of all classes, and subclass of no class. This is the grandmother of all classes -- the Object class. Now you know why all classes 'automatically' have a toString() method and an equals() method: these classes are public, are defined in the Object class, and are thus available to all subclasses (and subsubclasses, and subsubsubclasses....) by inheritance.

So the memory model really looks like this:

Figure 29: Memory model showing Student object

Look up the Object class in your API to see what other attributes you get for free!

The idea of inheritance is that it should save us time and make it easier for us to write correct software. Imagine that you've written a fairly complicated class, and now you need to write another class which is very similar to the first class, but with a few differences. Now of course you could 'cut and paste' the first class, rename it, and then change whatever needs to be changed. However this approach violates one of our important software engineering principles: 'don't write the same code in two different places'. Writing in two different places makes debugging twice as difficult, and means that if we change design we have to change code in two or more different places. However, with inheritance we can write the code in one place, making it easier to debug and maintain.

There are more aspects to using inheritance, which we'll discuss in the coming sections.


next up previous
Next: Week 11 Up: Week 10 Previous: Vector class
Chris Trendall
Copyright ©Chris Trendall, 2001. All rights reserved.

2001-12-09