Search code examples
javainheritance

Java Inheritance forcing me to do things I don't want when super() is called


I'm reading the official Java tutorials on the Oracle website and I am not liking what I see when experimenting with Inheritance.

I created a Bicycle class and a MountainBike class that extends Bicycle. MountainBike is forced to call super() on Bicycle's constructor from within its own constructor, but this is what happens:

A Bicycle has been created.
A Bicycle has been created.
A MountainBike has been created.

When the classes look like this (snippet):

public Bicycle(int speed) {
 this.speed = speed;
 System.out.println("A Bicycle has been created.");
}

public MountainBike(int seatHeight, int speed) {
 super(speed);
 this.setSeatHeight(seatHeight);
 System.out.println("A MountainBike has been created.");
}

This is not desired behavior.

  1. Is this a common drawback of Inheritance?
  2. What do you do in this case?

Solution

  • What is the drawback? The MountainBike class calls the Bicycle constructor and therefore you will see the output of "A Bicycle has been created." before you see the "A MountainBike has been created." output.

    If you are saying that you don't want to see the "A Bicycle has been created." output when creating a MountainBike, you may want to wrap the creation of the Bicycle or MountainBike with another class that knows which output to display. But essentially what you see in the output is what you would expect to see as a MountainBike is also a Bicycle.

    public class BikeWarehouse {
    
        public Bicycle buildBicycle(int speed) {
            Bicycle bicycle = new Bicycle(speed);
            System.out.println("A Bicycle has been created.");
            return bicycle;
        }
    
        public MountainBike buildMountainBike(int seatHeight, int speed) {
            MountainBike mountainBike = new MountainBike(seatHeight, speed);
            System.out.println("A MountainBike has been created.");
            return mountainBike;
        }
    }
    

    Or you could put a toString() method in the Bicycle and MountainBike classes and then when you create either, you can just have:

    System.out.println("A " + bike + " has been created");
    

    Obviously the toString() of the Bicycle would return "Bicycle" and the toString() of the MountainBike would return "MountainBike".

    I also don't use aspects too often but I believe it is possible to do something similar to the above without littering your code base (if you find the above "littering"), but you may be able to log on creation of your objects using something like AspectJ. I'm not a big fan normally of too many aspecting based solutions but might be something to consider.