5

When I extend some class,for example:

public class First {
    int id;
    public First(int _id) {
        id = _id;
    }
}

and

public class Second extends First {

}

I must redeclare the constructor for Second class, when I just need to do the same. I can:

public Second(int _id) {
    super(_id);
}

But every time I change the parent constructor all of the extended classes' constructors need to be edited.

How can I extend the constructor fully?

Damn, don't tell me about phone and antenna, I have used OOP many times.

Now I only ask - can't I write public Class(){} on extended classes, and use the parent constructor?

It seems that I can't. Okay.

James Martinez
  • 191
  • 2
  • 11
ShadowPrince
  • 127
  • 1
  • 1
  • 8
  • 10
    You can't? This is how it works. You change something in the super constructor, you have to change all the children which inherits from it. – OmniOwl May 20 '12 at 16:17
  • 2
    Its embarrassing for me, i can't belive that java can't. – ShadowPrince May 20 '12 at 16:18
  • 3
    Let's say your parent class is Phone, and that a Phone needs a screen and an antenna to be built. If subclass instances were allowed to be constructed without antenna, they wouldn't be phones anymore. You may however provide a constructor in the parent class which only takes a screen as argument, and uses a default antenna. – JB Nizet May 20 '12 at 16:21
  • 1
    When you change parent constructor, the child constructors `super` call also get changed. I don't see your question, nor do I see the problem. –  May 20 '12 at 16:21
  • 1
    Don't think of the constructor as a method. Think of the constructor as asking to have the class. When class b inherits class a, if you use the 'inherited' constructor, you are asking for class a, not class b. This is why it doesn't make sense to inherit and use the constructor, if you want class b, you user class b's constructor – dann.dev May 21 '12 at 01:41
  • "*Damn, dont tell me about phone and antenna, i use OOP many times*" -- Not sure why but I actually laughed when I read this. That's the spirit *ShadowPrince*. – Daniel Jan 20 '15 at 16:13

2 Answers2

10

When you define a subclass, it does not inherit constructors from the superclass. For anything other than the default superclass constructor, you need to explicitly call a superclass constructor in each subclass constructor. (That means, among other things, that if the base class does not have a default constructor, neither can any child class every child class constructor must explicitly call a superclass constructor—and no child class can have simply a compiler-generated default constructor. There's one exception to this; see [*] below.)

Inheriting constructors could cause all sorts of problems. Imagine something like this:

class Base {
    private int mId;
    public Base(int id) {
        mId = id;
    }
    . . .
}

Now we want to derive a class that has a second attribute—a tag—that we want to ensure is never null. So we write the following:

class Derived extends Base {
    private Object mTag;
    public Derived(Object tag, int id) {
        super(id);
        if (tag == null) {
            throw new IllegalArgumentException("tag cannot be null");
        }
        mTag = tag;
    }
    . . .
}

Now imagine constructing an instance of Derived like this:

Derived derived = new Derived(3);

If constructors were inherited, this would presumably be legal. What would it mean? For one thing, mTag would be set to its default value of null. There would be no way for Derived to enforce the rule that all instances of Derived must have a non-null tag.

At the cost of requiring a bit more typing, Java rules out inheriting constructors precisely to allow each class to fully control how its instances get created.

[*] There's one case where the compiler will automatically generate a non-default constructor. Consider the Base class above and this code:

Base foo = new Base(3) {
    . . . // some extended functionality
};

Now foo is being initialized to an anonymous subclass of Base. For ease of reference, let's call this subclass Base$Anon. The compiler will generate code equivalent to:

class Base$Anon extends Base {
    Base$Anon(int id) {
        super(id);
    }
    . . . // some extended functionality
}

Base foo = new Base$Anon(3);

This is the only case where the compiler generates a non-default constructor if you don't specify any constructors of your own. In fact, the language syntax doesn't even let you declare a constructor for an anonymous class; you must rely on the compiler generating one for you.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • I just want to not type contructor for each class, and use contructor from parent. Bad, but its impossible, i see. – ShadowPrince May 20 '12 at 16:44
  • @ShadowPrince IDE's like eclipse can generate the constructor's from the superclass, perhaps this is actually what your looking for? – dann.dev May 21 '12 at 01:42
2

This limitation is one of the reasons why I prefer composition over inheritance. Consider using code like this instead:

public class Second {
    private final First first;

    public Second(final First first) {
         this.first=first;
    }

    public int getId() {
        return first.getId();
    }
}

This construct also leaves your two classes less coupled and makes the relation between the classes clearer in my opinion. For a more thorough discussion of composition over inheritance, see for instance this question: Prefer composition over inheritance?

Community
  • 1
  • 1
Alexander Torstling
  • 18,552
  • 7
  • 62
  • 74