|Java Class Inheritance|
|Written by Ian Elliot|
Page 3 of 4
What if you inherit a function that doesn’t do the job that you want it to?
No problem, you simply override it!
(Not to be confused with overloading introduced earlier.)
If you create a new function with the same name and signature as an inherited one it is your new member function that wins out and will be used.
That is the new version overrides the old.
For example, Point.Swap() might be better defined, for strange geometric reasons, in PointColor as a function that swaps each coordinate and changes the color in some way. So let's override the version in Point with a new version in PointColor-
Now when you used PC.Swap() it is this new version in PointColor that is used. That is in:
the new overriding Swap function is used. However in
the original Swap is used.
The only problem is that the new Swap function doesn’t work because X and Y are private data members and not even PointColor, a descendant of Point can get at them! A correct version of Swap would have to use the access functions just like any other function outside of the point class -
An alternative would have been to weaken the protection of the private members to protected. Protected is like private in that the outside world cannot get at protected members but classes that extend a base class can access them. This is a weaker sort of protection that allows classes that are based on other classes access to the inner workings - this if best avoided if possible because it makes it more likely that a change to the base class will break the derived classes.
It is also modern Java practice to add an annotation to an overridden method to make sure that you know that it overrides an inherited method:
Generating An Override - Super And Object
As you might also guess NetBeans provides a way to help you override inherited classes. Right click were you want to generate the override code and select Override Methods:
Next select all of the methods you want to override and NetBeans will generate the code for you:
The typical generated code for an override is:
This raises a few questions. The first is what is
The answer is that a derived class can call a base class method even if it has overridden it using super.method(). The keyword super refers to the base or super class that is inherited by the derived or subclass. Notice that the generated code calls super.getX() and therefore the overridden method does exactly what the inherited method does and hence this is a good place to start applying modifications. It is often the case that an overridden method will call the base class method as a first step in its implementation and this seems entirely reasonable but it doesn't have to.
The next question is what is Object in the list of methods that could be selected for overriding?
A class can inherit from another class which in turn can inherit from another class and so on. Each class can only inherit from one class but there might be a chain of base classes that each class extends. If you don't specify a base class then the default class Object is used. That is in Java all chains of inheritance start with Object which is the only class that doesn't extend another class. The Object class provides some basic methods such as toString etc. which are generally useful to any class. In most cases however you have to override them to make them really useful - hence the reason for the Object methods being listed in the list of possible methods to override.
If you think about it for a moment all classes inherit from some class be it Object or a specific class. This means that inheritance takes that form of a hierarchy or family tree with Object occupying the top most position. More about this idea later.
Constructors and inheritance
Don’t read this unless you have understood inheritance and are happy with it!
There is an interesting little problem with inheritance and one that is usually ignored by most introductions, and even slightly advanced texts, on Java.
When you create a new class by inheritance what happens to the constructors?
After all the original or parent class might have a constructor defined which is essential to initializing its members but when you create an instance of the child class it is the child's constructor that is involved so how does the parent get initialized?
The answer to the problem of inherited constructors is that when an instance of the child class is created the system tries to call the default constructor of the parent and then calls the default constructor of the child class.
If there are explicit constructors, i.e. ones you have written, then things get more complicated. The system will first try to call the default constructor of the parent, i.e. one without parameters. If a parameter-less constructor doesn’t exist then the system stops with an error message. If one does exist is then it carries on and uses it.
Now this only leaves the problem of what to do if the parent has a constructor with parameters and you actually want to use it?
The answer is that you include the call super(parameters) in the child's constructor. This calls the appropriate parent's constructor with the parameters as specified and stops the system calling the default.
You met super in the previous section as a way of calling any method in the base class and it also works for constructors with the small difference that you simply use super() and not the name of the class.
This is complicated but consider the PointColor class introduced earlier. Its constructor should initialize all three member variables X, Y and Color. Two can be initialized by the Point’s constructor -
This results in the constructor Point(int,int) being called to set X and Y. Of course if you have an inheritance chain the constructor calls work their way back to the mother of all classes… which is Object.