Constructors & inheritance

majestic0110 3 Tallied Votes 578 Views Share

I just wanted to demonstrate a quick point regarding Constructors & inheritance.
Look at these two classes and think about what you might expect to see after the main method has run.
Notice that ClassB is a subclass (inherits from) of ClassA. So, what do we expect the output to be? Here's the output:

run:
Class A constructor
Class B constructor
BUILD SUCCESSFUL (total time: 0 seconds)

As you can see, the main method makes an explicit call to ClassB's constructor, but not ClassA's constructor. ClassA's constructor, is, however called implicitly because ClassB is a subclass of ClassA. An important thing to note is that ClassA's consructor actually finishes executing BEFORE ClassB's constructor! Take a look at this code:

----------------------------------------------------------------------

public class ClassA
{
	public ClassA()
	{
		System.out.println("Class A constructor");
	}
}

----------------------------------------------------------------------

public class ClassB extends ClassA
{

	public ClassB()
	{
		System.out.println("Class B constructor");
	}

	public static void main(String[] args)
	{
		new ClassB(); // explicitly call ClassB constructor
	}

}

----------------------------------------------------------------------
masijade 1,351 Industrious Poster Team Colleague Featured Poster

Because the first line of every constructor, is a call to a super constructor. If you do not add it yourself (i.e. call a specific super constructor) the compiler automatically adds a call to the default constructor of the super class. And, yes, obviously, this call will finish before the constructor in which it is to be found. To be complete your code is actually as follows:

public class ClassA {
    public ClassA() {
        super();  // the default constructor of Object
        System.out.println("Class A constructor");
    }
}

public class ClassB extends ClassA {
    public ClassB() {
        super();  // the default constructor of ClassA
        System.out.println("Class B constructor");
    }

    public static void main(String[] args) {
        new ClassB(); // explicitly call ClassB constructor
    }
}
majestic0110 187 Nearly a Posting Virtuoso

Thanks for that input masijade, I have found that the call to super() is often omitted in these circumstances, and that explicitly calling super() is redundant, because it is called implicitly. It does, however, improve code readability to show our call to super() as the first statement. So, good point and thanks for viewing! :)

masijade 1,351 Industrious Poster Team Colleague Featured Poster

That is what I said, that super() is added by the compiler, if you don't add a super call yourself. I simply illustrated what the code effectively was. In fact, if your classes looked like this

public class ClassA {
    public ClassA(String s) {
        System.out.println("Class A constructor " + s);
    }
}

public class ClassB extends ClassA {
    public ClassB() {
        System.out.println("Class B constructor");
    }

    public static void main(String[] args) {
        new ClassB(); // explicitly call ClassB constructor
    }
}

You will get the compiler message "Implicit super constructor ClassA() is undefined. Must implicitly invoke another constructor."

majestic0110 commented: Thanks for your input! +6
majestic0110 187 Nearly a Posting Virtuoso

That's great, thanks for your input on this snippet. The clearer it is to others, the better!

java_programmer 0 Junior Poster

I just wan to add one point -
If you define a constructor in a class, you must have to define the default constructor(without parameter) also, otherwise you will get an compilation error.

That's great, thanks for your input on this snippet. The clearer it is to others, the better!

masijade 1,351 Industrious Poster Team Colleague Featured Poster

I just wan to add one point -
If you define a constructor in a class, you must have to define the default constructor(without parameter) also, otherwise you will get an compilation error.

Sorry, but not if you don't want that the "default constructor" be used, or when it is not applicable. Such as when a class revolves around a specific instance variable and that a class that doesn't have it defined is "useless" and a default value makes no sense, than a "default constructor" also makes no sense, so you define a constructor with which that value can be set and do not define a "default constructor". That way, any class extending that class must explicitly call that super constructor, thereby keeping the "extended class" valid.

I.E. here is an example (a bit construed but valid)

package ages;

public class Age {
  private int age;

  public Age(int age) { this.age = age; }

  public int getAge() { return age; }
}

---------------------------------------

package ages;

public class OldAge extends Age {
  private static final int minAge = 65;

  public OldAge() {
    super(minAge);
  }

  public OldAge(int age) throws NotOldEnoughException {
    super(age);
    if (age < minAge) throw new NotOldEnoughException();
  }
}

See, the Age class needs an age, and what should be the default age? There is no sensible value, and an Age without an age value is also nonsensical, so there is no default constructor. Therefore, all constructors of OldAge must explicitly call the super(int) constructor.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.