2
class Animal {
    protected Animal(){
        System.out.println("ANIMAL CONSTRUCTOR");
    }
    public void move(){
        System.out.println("ANIMAL Move");
    }
}

class Dog extends Animal{
    public Dog(){
        System.out.println("Dog Constructor");
    }
    public void move(){
        System.out.println("Dog move");
    }

}


public class Test {
    public static void main(String args[]){
    Dog d = new Dog();
    d.move();
    }
}

The code above yields the result below:

ANIMAL CONSTRUCTOR 
Dog Constructor
Dog move

It seems that when dog instance is created, it also calls Animal constructor by default (implicitly).

Which is strange because I was thinking explicitly calling super() can do the same job.

Is there any way to break this constructor chain and let my dog instance only call Dog constructor?

if there is not, is there reason for it?

Keon Kim
  • 740
  • 3
  • 12
  • 27
  • 3
    I think this might be an XY problem http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem Why don't you want the `Animal` constructor to be invoked? – Paul Boddington Nov 16 '15 at 16:32
  • "Why" sets this question apart from the originally-identified question it was marked as a dupe of. That said, there almost certainly *is* an earlier version of this question that this could be closed and point to. – T.J. Crowder Nov 16 '15 at 16:37
  • This question is largely (entirely?) answered by [this question and its answers](http://stackoverflow.com/questions/2967662/any-way-to-not-call-superclass-constructor-in-java) combined with [this question and its answers](http://stackoverflow.com/questions/7173019/why-is-constructor-of-super-class-invoked-when-we-declare-the-object-of-sub-clas). – T.J. Crowder Nov 16 '15 at 16:41

2 Answers2

8

It seems that when dog instance is created, it also calls Animal constructor by default (implicitly).

Yes.

Which is strange because I was thinking explicitly calling super() can do the same job.

You can, yes, but if you don't, the compiler inserts a call to super() (with no args) at the beginning of your subclass constructor. The reason for allowing you to do it explicitly is that you may want to call a superclass constructor that accepts arguments.

Is there any way to break this constructor chain and let my dog instance only call Dog constructor?

No.

if there is not, is there reason for it?

Because Dog is a(n) Animal, and so the Animal class must have its chance to initialize the Animal-specific features of the object being created.

Consider:

class Animal {
    private Something useful;

    Animal() {
        this.useful = /*...something useful...*/;
    }
}

class Dog extends Animal {
    private String breed;

    Dog(String breed) {
        this.breed = breed;
    }
}

When you construct a Dog instance, in memory it looks like this:

+-------------+
|     Dog     |
+-------------+
| useful: ... |
| breed:  ... |
+-------------+

A Dog instance is a combination of what's defined by Animal and what's defined by Dog.

Now, suppose Animal's constructor were never called: What value would useful have? Right! null (because I declared it as an object type). But Animal's code quite clearly expects the constructor to set useful to something useful. If we could somehow bypass Animal's constructor, we'd be breaking the class.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • so `super()` is used to make it clear that it is inherited or to select from many other constructors? – Keon Kim Nov 16 '15 at 18:20
  • @KeonKim: Yes. `super()` (literally, with no arguments) is purely a matter of style. I always do it, for instance, for exactly those reasons: To be clear about what's going on and specifically that I'm calling the no-arguments version. But some people quite reasonably argue that I shouldn't because the compiler always does it anyway and so they find it jarring to see it explicitly written. When you call `super(with, args, here)`, of course, that's required, because the compiler will never do that for you. (Not even when the superclass doesn't have a no-args constructor.) – T.J. Crowder Nov 16 '15 at 18:30
2

There is no way of stopping the Animal constructor from being called when you instantiate a child class. Essentially that's because the base class might contain fields that need to be set too.

(Note that the constructor to the implicit base class java.lang.Object is also called. You question is more about "missing out a constructor" somewhere in the inheritance heirarchy).

You could make Animal an interface if it doesn't contain any fields. Then it will not have a constructor. Using interfaces in this way allows you to define, for example, movement-like methods on objects that are not animals, such as vehicles. You are then stumbling upon a programming paradigm called composition.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483