views:

400

answers:

10
class A{

    A(int x){}
}

class B extends A{

    B(int x){}

    public static void main(String args[]){
         B b = new B(10);
    }
}

I understand this would throw an error (one-arg constructor for B, implicitly calls super(), whereby no default-arg constructor exists for A). I am curious why one-arg constructor for B, does not use super(x) to call one-arg constructor of class A. On the contrary, putting me into the hassle of explicitly writing a no-arg constructor for A, when I don't require one!

A: 

You should then explicitly call super(x) at the beginning of your function. Basically Java will add a call to super() if it does not find a call to super of any kind -- so add your own and you will be fine.

Adam Luter
`B(int x){ super(x); }` is what I mean, btw.
Adam Luter
+2  A: 

All you need to do is

B(int x){ super(x); }

There's no need for a default constructor but you do need to call the one-arg constructor from A.

Seems like the compiler could help you out here but Java is verbose like that sometimes.

Matt
explicit is better than implicit. -Zen of Python
Jweede
+10  A: 

You can rewrite your B class like so:

class B extends A{
    B(int x) {
        super(x);
    }
}

which will do what you want. It doesn't happen implicitly, since there can be lots of different constructors in A (in your example there aren't, but there could be) and it wouldn't know which one was the right one. What if you had one class that took a length and a width, which for some reason override a class that took a width and a height. You wouldn't want Java to automatically call the superclass constructor simply because the types of the arguments matched. You would want a compile error, forcing you to explicitly call a superclass constructor with the appropriate/correct arguments.

Adam Batkin
+1  A: 

A no-arg constructor you always know what it does, as it doesn't depend on any externaldata; OTOH a constructor with some arguments the compalier can't be sure what they mean so it ask you (the human) to confirm which one to use.

Example given:

class A{
    A(int numberOfYears){}
}

class B extends A{

    B(int numberOfApples){}

    public static void main(String args[]){
         B b = new B(10);
    }
}

I guess this shows more clearly why the compiled doesn't use that super(int) constructor by default.

lapo
You didn't provide a solution to his problem, but you did illustrate why java probably shouldn't automatically accept his code as-is.
Adam Luter
Whops, I forgot the last sentence. But Adam Batkin's answer is better anyways, since does a concrete example (length vs width) as opposed as my quite abstract one (years vs apples).
lapo
+1  A: 

As the Zen of Python tells us: Explicit is better than Implicit

So change B(int x){} to B(int x) { super(x); }

Jweede
+4  A: 

The reason you get an implicit zero-arg constructor call for super is that the compiler does know that you want the super constructed - it just wouldn't make sense otherwise - and the zero-arg constructor is a simple, natural, and generally correct choice. Asking the compiler to be any smarter about it than that is unrealistic. You can say, "hey, there's only one constructor, and it takes the same number of arguments - how hard could it be?" But it's really hard; the possibilities of what you might want in this case are wide open. So the safe policy is: if you want anything more than the no-arg constructor, the compiler requires you to call it explicitly.

Carl Manaster
A: 

Probably because the java designers figured it would be more likely that there is a default constructor in the superclass than that there is a constructor with the same signature that you want to call. Also maybe because the rule "if you don't invoke super explicitly, it uses the default constructor" is simpler than "if you don't invoke super explicitly, it uses the constructor of the superclass with the same signature".

sepp2k
A: 

I am curious why one-arg constructor for B, does not use super(x) to call one-arg constructor of class A.

If you are asking this as a language design question ...

I guess the Java designers thought that more complicated semantic for implicit super "call" would be harder to understand. For example, what if the type of the superclass constructor parameter was different to the parameter type in the subclass? What if there were multiple constructors in the supertype?

I personally don't think it is a burden to include an explicit super call in every constructor. Indeed, a lot of people think it is good style.

Stephen C
A: 

The reason is, when you define parameterised constructor in subclass, You want to OVERRIDE something from superclass. So the superclass is not called AUTOMATICALLY. You CAN however call the super(param) (in case you are just ADDING to the functionality). But that should be the first call.

However DEFAULT constructor is by its name DEFAULT. so it will ALWAYS be called (in JLS specified order) when an object is created.

Sarath
A: 

As others have pointed out, in the example you give it wouldn't be a big deal to explicitly call the one-arg constructor.

What bothers me more is when I have a super class A with two subclasses, B and C, and B and C both require the same 10 constructors with a bunch of parameters. It seems to me that the whole point of inheritance is that I should be able to put those constructors in A and not have to write the same code twice, or even write 10 pass-thru functions twice.

If I can write an ordinary function in a class that is inherited by its subclasses, why can't I write a constructor?

I wonder if it's one of those problems where if I read the code for the compiler, I would find myself saying, "Ah, I see, if they had tried to do that they would have run into this and that problem, and it would have just been an ugly mess." Or maybe they were just brain-dead the day they wrote that code. I've never really heard a satisfying explanation of why this couldn't have been made to work.

The one idea that occurs to me: Suppose B extends A. A has a function x() that returns an int. B inherits this function, so B now has a function x() that returns an int. A has a constructor A that, in effect, returns an object of type A. But a constructor for B would have to return an object of type B, not A. So it isn't really inherited, it would have to be more like "extrapolated" than inherited. So it's not quite the same thing.

Still, to say that if I have class A with constructor A(int x, int y) and B extends A that the compiler could automatically generate a constructor B(int x, int y) that calls A ... that seems like it should be do-able. Sure, maybe that's not what I want to do. But then give me a way to override it, like by explicitly declaring a different construct B(int x, int y). In real life, I almost always reproduce all my constructors in sub-classes.

Jay