For example I have this:
class A{
private int mine = 0; //Some field...
public A(int a){mine+=a; /*Some operation1...*/}
}
class B extends A{
private int mine = 0; //Some field...
public B(int a){mine-=a; /*Some operation2...*/}
}
and I get:
error: constructor A in class A cannot be applied to given types;
public B(int a){}
required: int
found: no arguments
reason: actual and formal argument lists differ in length
1 errors
I don't understand the error? What is telling me to do?
Though, the code works if Constructor of "A" has no arguments. But I need to do the Operation1 (aka mine+=a;), so I need A's arguments, but then I fail.
I'm closed in this magic circle. What shall I do?
The first instruction of every constructor is always to invoke one of its superclass constructor. If you don't do it explicitely, the compiler inserts this instraction for you. The constructor
public B(int a) {
mine-=a;
/*Some operation2...*/
}
is thus equivalent to
public B(int a) {
super(); // invoke the no-arg super constructor
mine-=a;
/*Some operation2...*/
}
Since A doesn't have a no-arg constructor, the compilation fails. In this case, you must explicitely invoke one of the super constructors:
public B(int a) {
super(a);
mine-=a;
/*Some operation2...*/
}
Every constructor must call a superclass constructor as the first thing it does. If you do not do it explicitly via super(), the compiler will implicitly call the no-arts constructor in the superclass. But in your case, the superclass does not have a no-args constructor, at which point the compiler gives up.
By the way, it's generally a very bad idea to re-declare a field in a subclass, because it will hide the superclass field, but there will still be two fields.
I think you need to call class A's constructor from B constructor, like this:
super(a);
If B extends A, the first operation of the constructor of B is, to call the constructor of A.
If there is no constructor explicitly defined in A, the standard constructor is called. If you don't call the ctor explicitly, it is called implicitly.
But if there is an explicit ctor, which takes arguments, it isn't called automatically - how should it - with which arguments? You have to call it yourself.
But your class hierarchie is somewhat misterious. If you want to access mine in the subclass, make it protected or leave it in default state - don't make it private.
If you make it private, a new introduced attribute with the same name hides the parent attribute, but this is errorprone and irritating.
In most cases, access, maybe via a method (getter/setter), would be better, or opening the visibility.
Or a different name for the thing in the subclass.
Related
As per constructor chaining base constructor should be called when a derived class object is created and assigned to base class reference.
And there is no default constructor in base class but then there is an explicit parameterized constructor, so java compiler does not provide default constroctor.
Without the statement "this(10);" compiler complains but then as soon as its added, compiler is fine with it. WHY??
I mean why does it not try to call the base class default constructor after adding "this(10);". It should have done a super call and then executed the added statement.
class Parent{
public Parent(int a) {
System.out.println(a);
}
}
class Child extends Parent{
public Child(){
this(10);//default value
}
public Child(int a) {
super(a);
System.out.println(a);
}
}
The Java Language Specification (§12.5) defines what happens when you create a new instance; I highlighted the most important parts for your question.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
So, the key points are:
Your first constructor explicitly invokes the second constructor, so step 2 above applies; the second constructor is executed, and then step 3 is skipped.
Step 3 is where the superclass constructor gets called, so that means when a constructor invokes another constructor from the same class, then it does not directly invoke a superclass constructor.
However, if you delete this(10); from the first constructor, then the first constructor does not invoke another constructor of the same class, so step 3 applies, and a superclass constructor is implicitly invoked. This causes an error because there is no superclass constructor that can be implicitly invoked (with no arguments).
The default/implicit constructor is there only if there is no other constructor.
By adding
public Parent(int a) {
System.out.println(a);
}
you remove the default constructor of Parent.
If you want to keep the default constructor, you can write it yourself like this:
public Parent(){
}
The following constructor
public Child(){
}
will be automatically replaced to
public Child(){
super();
}
This replacement will happen if there is no constructor call(this() or super()) in the first line.
This secures that a super constructor is called in any case.
The replacement will fail if there is no constructor without arguments in the super-class (if you have replaced the default constructor with a parameterized constructor).
Because if you don't add this() to Child() constructor - compiler will insert super() statement and thus expect no-arg constructor in Parent class.
class Parent{
public Parent(int a) {
System.out.println(a);
}
}
class Child extends Parent{
public Child(){
// this(10);// Commenting this(10) as if it did not exist.
super() // inserted by compiler unless you put this() or super() yourself
}
public Child(int a) {
super(a);
System.out.println(a);
}
}
Why should a class call the call the Objects default constructor of the class Objects when the class already has a parametrized constructor and a unparametrized constructor?
Example
public abstract class Foo{
private int dim1;
public Foo(int dim1) {
super();
this.dim1 = dim1;
}
public Foo() {
this.dim1 = 0;
}
}
2. Why isn't the super() method called in the unparametrized constructor in the example above?
What could happen if I forget or I don't want to call the constructor in the Object class with super() ?
Does it matter if the class which calls the super() method (Unparametrized Object's class constructor) is abstract or not ?
Why should a class call the call the Objects default constructor of the class Objects when the class already has a parametrized constructor and a unparametrized constructor?
Just because of you have it, it doesn't mean it gets called automatically. You have to call it and that is where object instantiation begins.
Why isn't the super() method called in the unparametrized constructor in the example above?
It is not a method. It is just invoking the super class default constructor. Do you know , if you didn't call it, the Java compiler automatically inserts that statement while giving you byte code. So you need not write that super() in child constructors unless you want to call specific constructor .
What could happen if I forget or I don't want to call the constructor in the Object class with super() ?
Don't worry. As said above, compiler inserts it for you.
Does it matter if the class which calls the super() method (Unparametrized Object's class constructor) is abstract or not ?
Yes, abstract or not doesn't matter. It just calls the super class constructor.
1) You probably shouldn't. It is unnecessary. It is an extra line of code which doesn't do anything.
2) Because explicitly calling super() is entirely unnecessary if your object does not extend a class other than Object (as all classes do). You could remove it from the first constructor and nothing would change. The code would compile identically.
3) Nothing. You're not required to do it.
4) This makes no difference.
See below example:
class A {
A() { this(1); }
A(int i) { System.out.println("A" ); }
}
class B extends A {
B() {}
B(int i) { System.out.println("B" ); }
}
public class Test
{
public static void main(String[] args) {
A o = new B();
}
}
The output:
A
Q1:Seems java does not perform late binding for "this(1)". It has been decided at compile-time.Please confirm.
Q2:Java does not perform late binding on any constructors. Please confirm.
Q3:Does this mean constructors are implicitly final?
You cannot override constructors. They don't follow inheritance rules at all. They can't follow inhertitance rule because you need a simple order for constructing your object.
e.g. in your example, if you could override the A(int) constructor A() would call B(int), but B(int) implicitly calls super() which is A() and you have infinite recursion.
It is often considered bad practice for a constructor to call an overrable method. So having constructors do this automatically would be a very bad idea.
If the constructors were final, like static final methods you wouldn't be able to hide them either, but you can, so I would say they are final either.
Java does not override the constructor.
A o = new B();
It will call B() wherein it will call super().
A() will be called and here you are calling this(1) which means it will call A(1) so nothing strange .Everything is decided at compiletime when you talk about constructors.
Answers:
Q1:Seems java does not perform late binding for "this(1)". It has been decided at compile-time.Please confirm.
Yes,Only at compile time constructors are decided.
Q2:Java does not perform late binding on any constructors. Please confirm.
Since doesn't override so no late binding.
Q3:Does this mean constructors are implicitly final?
No they are not final but you cannot override them.
EDIT:
A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass. Refer Java Docs
Q1: true
Q2: that is not about the constructor, it is more about this. this always refer to a method/field present in the class or the super class, not in the children. That makes sense since the parent does not know the implementation of the child
Q3: Kind of, Constructors are special method and it does not make sense to override them since they are chained
When you create an instance of a subclass, you must invoke a constructor of the superclass.
If you don't specify a constructor, the default (no-args) constructor is called for you.
In other words, the no-args constructor in B, is actually executed as:
B() {
super();
}
When you instantiate a subclass constructor, it first invokes its superclass' default constructor before performing its own task. This is done implicitly or via super() reference.
So a call to B() will call constructor A() which will call A(1)
Similarly if you call B(2) the output will be ( It will call default constructor A() and then A(1)
A
B
'"this()" is not overridden' doesn't mean anything, and neither do any of your other questions.
All that is happening here is that the constructors for B are both implicitly calling super(), because you didn't code anything else, and super() is A(), which calls this(1).
While studying for my finals, I came across the following statement in the book from which I am currently studying. Considering the following code :
class A {
public A(int x) { }
}
class B extends A {
public B(int x ) { }
}
is it mandatory to call the constructor of class A in the constructor of class B(super(x)). The book states that it's not mandatory, because they have the exact number and type of parameters. But when I try this in a java compiler, the following error gets thrown :
constructor A in class A cannot be
applied to given types; required:
int found: no arguments reason:
actual and formal argument lists
differ in length
The compiler automatically inserts super() in the beginning.
However, even constructors arguments, super() (without arguments) is added which invokes the default constructor of the superclass. And you don't have one, hence the error.
You have to specify super(x) (to invoke A(x)), or define a no-argument constructor.
By the way, Eclipse compiler gives a way better error message:
Implicit super constructor A() is undefined. Must explicitly invoke another constructor
It looks like the compiler tries to create a call to the superclasses default constructor with super(), which isn't avaliable:
required: int
found: no arguments
But back to your book: I've never heard of a rule that you can skip the super statement in a constructor if the actual constructor has the exact same parameter list as a constructor in the direct superclass. Only a call to the superclass's default constructor is added implicitly (super()) but that requires that the superclass has a default constructor.
In contrast to what's written in your book (or in contrast to your understanding of the written text), here's a sentence from the language spec:
If a constructor body does not begin with an explicit constructor invocation
and the constructor being declared is not part of the primordial class Object, then
the constructor body is implicitly assumed by the compiler to begin with a super
class constructor invocation “super();”, an invocation of the constructor of its
direct superclass that takes no arguments.
If you have a the base class having a default constructor (no-arg constructor), when you extend B, you don't need to explicitly call super() because it is called any way.
But when you have a constructor with arguments, when making the contructor with parameters in B, you need to pass in super() a parameter for A
example :
class A {
public A(int x) { }
}
class B extends A {
public B(int x )
{
super(x); // need to specify the parameter for class A
//...
}
}
This happens when you dont have a default constructor and you are creating an instance with default one. Because If you have any Parameterized constructor then compiler will not insert the default one for you, instead you have to define.
It is neccessary to call constructor of super class in case of Java. Therefore, whenever you generate constructor of sub class, super class' constructor is self created by IDE.
It is because whenever base class constructor demands arguments, compiler thinks they are to be filled by base class constructor. In case of default constructor, it is OK. No need to call super() in sub class.
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!
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.
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.
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.
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.
As the Zen of Python tells us: Explicit is better than Implicit
So change B(int x){} to B(int x) { super(x); }
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.
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".
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.
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.
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.