210

I was wondering why in java constructors are not inherited? You know when you have a class like this:

public class Super {

  public Super(ServiceA serviceA, ServiceB serviceB, ServiceC serviceC){
    this.serviceA = serviceA;
    //etc
  } 

}

Later when you inherit from Super, java will complain that there is no default constructor defined. The solution is obviously something like:

public class Son extends Super{

  public Son(ServiceA serviceA, ServiceB serviceB, ServiceC serviceC){
    super(serviceA,serviceB,serviceC);
  }

}

This code is repetitive, not DRY and useless (IMHO)... so that brings the question again:

Why java doesn't support constructor inheritance? Is there any benefit in not allowing this inheritance?

Michael Celey
  • 12,645
  • 6
  • 57
  • 62
Pablo Fernandez
  • 103,170
  • 56
  • 192
  • 232
  • 3
    I agree that the constructor in `Son` is repetitive. It is for this reason that C++ now *allows* derived classes to inherit base constructors (see http://www2.research.att.com/~bs/C++0xFAQ.html#inheriting). Note that I emphasize "allow" because the derived class must explicitly declare that it uses the constructors in the base. – Derek Mahar Mar 27 '11 at 14:41
  • 1
    Like C++, Java would also benefit from syntax that permits constructor inheritance. – Derek Mahar Mar 28 '11 at 05:26
  • If you have a `private final int foo;` in the superclass `Super`, you can not assign a value to foo in the inherited Constructor in `Son` because its private in `Super`. – Grim Jun 26 '14 at 04:19

10 Answers10

226

Suppose constructors were inherited... then because every class eventually derives from Object, every class would end up with a parameterless constructor. That's a bad idea. What exactly would you expect:

FileInputStream stream = new FileInputStream();

to do?

Now potentially there should be a way of easily creating the "pass-through" constructors which are fairly common, but I don't think it should be the default. The parameters needed to construct a subclass are often different from those required by the superclass.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 41
    Why not *allow* a derived class to optionally inherit its base constructors as does C++ (see www2.research.att.com/~bs/C++0xFAQ.html#inheriting)? – Derek Mahar Mar 27 '11 at 14:57
  • 4
    A useful constructor syntax might be to allow a derived constructor to inherit the parameters of a base constructor and automatically forward these to the base constructor so that the derived constructor need not repeat these parameters. – Derek Mahar Mar 27 '11 at 15:01
  • 6
    What prevents you from just declaring the parameterless constructor to be private if you don't need it? – Mononofu Nov 14 '11 at 12:10
  • 7
    @Mononofu: Well it would certainly be annoying to have to create a constructor which would effectively create an unusable object and never be called, just to "remove" something which doesn't need to be provided anyway. Ick. I'd rather the language worked the way it does now :) – Jon Skeet Nov 14 '11 at 12:23
  • 2
    @Mononofu But wait ... To use that correctly and confidently, you would then have to understand java's weird systems of inheritance for BOTH constructors AND visibility. Isn't the world confusing enough already? ;) – Jan Jan 20 '12 at 00:40
  • @JonSkeet - "Now potentially there should be a way of easily creating the "pass-through" constructors which are fairly common, but I don't think it should be the default." Is that "there should be" => "there might be" or "there should be" => "there isn't but that'd be a good idea." ?? i.e., is there a way to "inherit" (for lack of a better word) all constructors of a superclass automatically?? – ryvantage May 10 '14 at 22:44
  • @ryvantage:There isn't but sometimes it would be useful to be able to do so concisely. I don't know of any plans around that. – Jon Skeet May 10 '14 at 22:48
  • If you're using Eclipse, you can right-click -> "Source" -> "Generate Constructors from Superclass..." to quickly achieve this. I imagine other IDEs have similar functionality. It might be nice to have this as a feature of Java itself, but this works pretty well. – Naliba May 29 '14 at 18:28
  • 1
    "> What exactly would you expect: `FileInputStream stream = new FileInputStream();` to do?" The same I expect `Object o = new Object()` to do: Nothing useful. – gcscaglia Aug 19 '15 at 19:00
  • Why not have a way for a base class to say "children should inherit this constructor?" – whoKnows Sep 07 '15 at 00:20
  • @whoKnows: That suggests that the superclass knows the requirements of the subclass. If the subclass wants to force *all* its constructors to accept an extra parameter, it doesn't *want* to inherit the constructors from the superclass directly. – Jon Skeet Sep 07 '15 at 05:17
  • And the base class can disable that constructor explicitly. – whoKnows Sep 07 '15 at 15:30
  • @whoKnows: And again, how would the base class know? It's more something for the subclass to decide. – Jon Skeet Sep 07 '15 at 15:46
  • @JonSkeet Whoops! I meant child class. – whoKnows Sep 08 '15 at 19:37
  • @whoKnows: That makes adding a new constructor a difficult change. Given that it's easy to create a new constructor that chains to the old one, I think opting in explicitly seems fine to me. – Jon Skeet Sep 08 '15 at 19:39
  • 1
    @JonSkeet How would that make adding a constructor a difficult change? – whoKnows Sep 11 '15 at 22:37
  • @whoKnows: Anyone adding a constructor to a superclass could effectively bypass the guarantees that subclasses required. For example, suppose I have a subclass such that *all* constructors must specify a particular parameter - for example, a `FileInputStream` must always have a filename supplied. If a new superclass constructor was *implicitly* "inherited" (i.e. duplicated in the subclass) then that duplicate may break that invariant. I really think it's a bad idea. – Jon Skeet Sep 12 '15 at 12:05
  • 1
    This is the exception rather than the rule. in this case, `FileInputStream` might want to disable that constructor, or the superclass might want to consider not making that constructor implicitly inherited. But in the vast majority of cases, the superclass would know that all of its children would want it to be implicitly inherited, or none. – whoKnows Sep 15 '15 at 00:03
  • @whoKnows: I think we'll have to agree to disagree. I think it's very common for all constructors of a subclass to enforce an extra piece of initial data to be passed in. Anyway, I don't think Java is going to change now... – Jon Skeet Sep 15 '15 at 05:44
  • @whoKnows I don't know that you could call this an "exception" so much as an example. **Any** superclass constructor that isn't used in the subclass *could* result in codebreaking behavior. This is true of many classes/programs, not just `FileInputStream`. It is better to require constructors from the superclass are called explicitly (which can be done very easily on an IDE like Eclipse anyway), than to assume that all imports/inherited constructors are properly restricted (and if not restricted, then inherited). What you are proposing would be very difficult to troubleshoot/maintain. – Monkeygrinder Dec 16 '15 at 01:02
  • (I also do agree with the notion of an optional "pass-through" though... but I'm not sure how much grief that would actually save in the long run) – Monkeygrinder Dec 16 '15 at 01:24
  • FileInputStream would work because it *overloads* the constructor. – u8y7541 Aug 21 '16 at 23:42
  • @u8y7541: No, you've missed the point - if all constructors are inherited, then it would end up indirectly inheriting the parameterless constructor from `Object`. Sure, the useful overloads would still exist - but so would the useless one. – Jon Skeet Aug 22 '16 at 06:29
  • 1
    My two cents: Java already has a mechanism whereby classes come with a default constructor but once a custom constructor is provided the default is removed. I think this mechanism could still work if default is defined as "all my superclass' constructors" instead of "constructor with no arguments". I think this will solve most of the problems mentioned above. Since `FileInputStream` declares a constructor that accepts a `String` this will invalidate the default constructor inherited from `Object`. – Benjy Kessler Sep 29 '16 at 11:46
  • @BenjyKessler: It wouldn't help in the common case where you basically want "all the constructors from the superclass, but with one extra parameter on each of them". So it would prevent that one specific problem, but not be a useful feature in other cases. It would also make the language more complex, IMO. It's clearly too late to change now anyway, of course... – Jon Skeet Oct 07 '16 at 14:42
  • @JonSkeet, that indeed be a very hard use case to support and indeed I would think very confusing and ambiguous. Consider Base that receives two ints and Derived that receives three. How would the compiler know how to choose the correct arguments to pass to Base? This seems confusing and wouldn't add much to the existing language. But I find myself often writing classes with the exact same constructors as the base class and this would help. As for the second point, a girl can dream can't she?! – Benjy Kessler Oct 09 '16 at 11:41
  • 1
    In 20 years of Java experience, my subclass constructors more often significantly differed from the superclass ones than they were identical or even similar. So I'm happy with Java's design decision. – Ralf Kleberhoff Nov 03 '17 at 09:57
34

When you inherit from Super this is what in reality happens:

public class Son extends Super{

  // If you dont declare a constructor of any type, adefault one will appear.
  public Son(){
    // If you dont call any other constructor in the first line a call to super() will be placed instead.
    super();
  }

}

So, that is the reason, because you have to call your unique constructor, since"Super" doesn't have a default one.

Now, trying to guess why Java doesn't support constructor inheritance, probably because a constructor only makes sense if it's talking about concrete instances, and you shouldn't be able to create an instance of something when you don't know how it's defined (by polymorphism).

James Dunn
  • 8,064
  • 13
  • 53
  • 87
David Santamaria
  • 8,671
  • 7
  • 33
  • 43
12

Because constructing your subclass object may be done in a different way from how your superclass is constructed. You may not want clients of the subclass to be able to call certain constructors available in the superclass.

A silly example:

class Super {
    protected final Number value;
    public Super(Number value){
        this.value = value;
    }
}

class Sub {
    public Sub(){ super(Integer.valueOf(0)); }
    void doSomeStuff(){
        // We know this.value is an Integer, so it's safe to cast.
        doSomethingWithAnInteger((Integer)this.value);
    }
}

// Client code:
Sub s = new Sub(Long.valueOf(666L)): // Devilish invocation of Super constructor!
s.doSomeStuff(); // throws ClassCastException

Or even simpler:

class Super {
    private final String msg;
    Super(String msg){
        if (msg == null) throw new NullPointerException();
        this.msg = msg;
    }
}
class Sub {
    private final String detail;
    Sub(String msg, String detail){
        super(msg);
        if (detail == null) throw new NullPointerException();
        this.detail = detail;
    }
    void print(){
        // detail is never null, so this method won't fail
        System.out.println(detail.concat(": ").concat(msg));
    }
}
// Client code:
Sub s = new Sub("message"); // Calling Super constructor - detail is never initialized!
s.print(); // throws NullPointerException

From this example, you see that you'd need some way of declaring that "I want to inherit these constructors" or "I want to inherit all constructors except for these", and then you'd also have to specify a default constructor inheritance preference just in case someone adds a new constructor in the superclass... or you could just require that you repeat the constructors from the superclass if you want to "inherit" them, which arguably is the more obvious way of doing it.

Christian Fries
  • 16,175
  • 10
  • 56
  • 67
gustafc
  • 28,465
  • 7
  • 73
  • 99
  • 1
    Your examples don't convice me. Just because you code bugs on purpose it is no valid argument against constructor inheritance. NullPointerExceptions are completely normal if you botch (and sometimes even if you don't). – The incredible Jan Aug 23 '17 at 06:30
  • @TheincredibleJan The point is that one important thing constructors are used for, is enforcing class invariants. Implicit constructor inheritance would make it much more complicated to give any guarantees about instances of a class (impossible, even, if you consider that constructors may be added to superclasses). – gustafc Aug 23 '17 at 07:14
  • 1
    This is not a good example. Your problem is that you are casting non-Integer Numbers to Integer. It has nothing to do with inheritance. – LowKeyEnergy Nov 22 '19 at 17:31
  • @LowKeyEnergy no, the problem is that being able to bypass constructors would deprive you of the only way you have to enforce class invariants. But, I admit my example could be more succinct - the point made in the accepted answer is more to the point; that everything would have a default constructor. – gustafc Nov 25 '19 at 08:14
6

Because constructors are an implementation detail - they're not something that a user of an interface/superclass can actually invoke at all. By the time they get an instance, it's already been constructed; and vice-versa, at the time you construct an object there's by definition no variable it's currently assigned to.

Think about what it would mean to force all subclasses to have an inherited constructor. I argue it's clearer to pass the variables in directly than for the class to "magically" have a constructor with a certain number of arguments just because it's parent does.

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
2

David's answer is correct. I'd like to add that you might be getting a sign from God that your design is messed up, and that "Son" ought not to be a subclass of "Super", but that, instead, Super has some implementation detail best expressed by having the functionality that Son provides, as a strategy of sorts.

EDIT: Jon Skeet's answer is awesomest.

Jonathan Feinberg
  • 44,698
  • 7
  • 80
  • 103
  • Super is in reality a LayerSupertype (http://martinfowler.com/eaaCatalog/layerSupertype.html) of my service layer. And I need the dependencies injected in the constructor to support DI. My design is not _messed up_ – Pablo Fernandez Oct 29 '09 at 15:18
  • Well, that's a matter of opinion! It seems to me that if your hierarchy is distorted to feed the requirements of your buzzword framework, that might in itself be a Sign from Above. – Jonathan Feinberg Oct 29 '09 at 15:33
  • Please explain why you say that my hierarchy is _distorted_. And I've never mentioned a buzzword framework, in fact I'm just using Guice + Plain old servlets. – Pablo Fernandez Oct 29 '09 at 20:35
  • I don't know whether your design is distorted, nor whether it's badly designed. I'm merely saying that if your subclass differs from its superclass *merely* by providing some difference in strategy, then in *may* be better expressed as a thing that the superclass *has* rather than *is*. I then said that if that's the case, but you still must design your software as a parent-child reltionship in order to support the needs of some framework (whether it's DI or whatever), then that's "distortion"! But I have no idea about how your software is designed. – Jonathan Feinberg Oct 29 '09 at 21:15
2

Constructors are not polymorphic.
When dealing with already constructed classes, you could be dealing with the declared type of the object, or any of its subclasses. That's what inheritance is useful for.
Constructor are always called on the specific type,eg new String(). Hypothetical subclasses have no role in this.

Rik
  • 28,507
  • 14
  • 48
  • 67
  • What the OP probably asks is "why do I have to make the super calls, when the compiler is perfectly capable of generating them for me?" – gustafc Oct 29 '09 at 15:22
  • ... which, for example, it does when the superclass has a default constructor and the subclass doesn't specify any constructors. – gustafc Oct 29 '09 at 15:24
0

Because a (super)class must have complete control over how it is constructed. If the programmer decides that it doesn't make sense to provide a default (no args) constructor as part of the class's contract, then the compiler should not provide one.

David R Tribble
  • 11,918
  • 5
  • 42
  • 52
0

You essentially do inherit the constuctors in the sense that you can simply call super if and when appropriate, it's just that it would be error prone for reasons others have mentioned if it happened by default. The compiler can't presume when it is appropriate and when it isn't.

The job of the compiler is to provide as much flexibility as possible while reducing complexity and risk of unintended side-effects.

clearlight
  • 12,255
  • 11
  • 57
  • 75
-1

I don't know any language where subclasses inherit constructors (but then, I am not much of a programming polyglott).

Here's a discussion about the same question concerning C#. The general consensus seems to be that it would complicate the language, introduce the potential for nasty side effects to changes in a base class, and generally shouldn't be necessary in a good design.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • 1
    C++ now allows derived classes to inherit base constructors (see www2.research.att.com/~bs/C++0xFAQ.html#inheriting). This avoids the common idiom found in derived classes where a derived constructor does little more than declare the same parameters as in the base constructor and forward these to the base constructor. – Derek Mahar Mar 28 '11 at 14:17
  • Python does: http://stackoverflow.com/a/6536027/2112722. Python also splits up the "constructor" phase into `__new__()` and `__init__()` methods, and has a very different approach to polymorphic methods. See https://pythonconquerstheuniverse.wordpress.com/2010/03/17/multiple-constructors-in-a-python-class/ – Sarah Messer Mar 20 '17 at 16:09
  • Any non typed language allows this – Alvaro Apr 12 '17 at 13:15
-2

A derived class is not the the same class as its base class and you may or may not care whether any members of the base class are initialized at the time of the construction of the derived class. That is a determination made by the programmer not by the compiler.

ChadNC
  • 2,528
  • 4
  • 25
  • 39
  • You don't have any option. Base class members *are* initialized by the time the derived class constructor code runs. Hard to see what this has to do with the question. – user207421 Jul 28 '23 at 05:55