If I have a superclass Animal with no attributes, and then another subclass Dog with one attribute, is it valid to use the super() method when creating the constructor for the subclass? Here's the example code:
public class Animal {
public Animal() { }
}
public class Dog extends Animal {
public int age;
public Dog(int age){
super(); // Do I include this?
this.age = age;
}
}
Is there any reason why I should or should not call the super() function in the Dog class, and does it make a difference? Thanks!
You don't need to call super() here as no-arg super class constructor gets called by default from subclass.
Only if there is a constructor in super class with some argument, then you need to call it from subclass explicitly if required.
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 implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.
This means that, if you don't have an explicit call or does have an explicit call to super(), the superclass needs to have a no-arg constructor - either an explicitly declared one, or a default constructor (a no-arg constructor automatically added by the compiler if the class has no other constructors).
As such, if the code compiles with the explicit super(), that means the super class does have a no-arg constructor: and so it would also compile and work equivalently if you omitted the super().
Related
This is test class that creates instance of Sub_Class
public static void main(String[] args){
Sub_Class s = new Sub_Class();
}
}
Here is Parent and Child class
public class Super_Class {
public Super_Class(){
System.out.println("This is Parent Class's Constructor");
}
}
class Sub_Class extends Super_Class{
public Sub_Class(){
System.out.println("This is Child Class's Constructor");
}
}
Constructors aren't herited then why it prints both constructor?
From the Java Language Specification, Section "8.8.7. Constructor Body"
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 implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.
So, yes, the constructor of the super is not inherited, but it must always be invoked. And if you do not invoke it yourself, then the compiler will do it implicitly for you. And if the compiler cannot do it, (because the super's constructor requires arguments,) then you will get a compile-time error.
A per the Java Tutorial
Note: If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
I am currently studying the concept of "class abstraction" and "extension" and have been wondering:
"If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?"
I understand the fact that extension instances the previous abstract class into the extended one and tries to call the default constructor but have been wondering why it gives out an error.
Is it because the constructor has been parametrized or simply because the empty constructor does not exist?
Does the extends keyword call something along the lines of this?
Object myClass = new AbstractClass();
And the missing parameters are the reason why it gives out an error so something along the lines of this would be correct
Object myClass = new AbstractClass(int foo,float boo);
And if that is it, does the super keyword essentially, if you'll allow me the term, "put" the parameters given in the parenthesis "inside" the constructor?
If that's not it what am I getting wrong? How does it actually work?
You should think of the extends keyword, in this context, as just saying that a class is the subclass of another class, and does nothing else. And that there are rules governing how subclasses and superclasses should work.
When you construct a subclass, you must construct its superclass first. For example, to create a Bird, you must first create an Animal. That makes sense doesn't it? To demonstrate this in code:
class Animal {
public Animal() {
System.out.println("Animal");
}
}
class Bird extends Animal {
public Bird() {
System.out.println("Bird");
}
}
Doing new Bird() will first print Animal and then Bird, because the Animal's constructor is called first, and then the Bird constructor. So actually, the Bird constructor implicitly calls the superclass' constructor. This can be written as:
public Bird() {
super();
System.out.println("Bird");
}
Now what happens if the super class does not have a parameterless constructor? Let's say the constructor of Animal now takes a String name as argument. You still need to call the superclass' constructor first, but super() won't work because super() needs a string parameter!
Therefore, the compiler gives you an error. This can be fixed by calling super() explicit with a parameter.
"If I declare a parametrized constructor inside my abstract class why
won't extension on another class work unless I declare myself the
constructor with the super keyword invoking the parameters of the
abstract class's constructor?"
Because the super class says that it MUST be constructor using that declared constructor and there is no other way around. This applies to every extending class - required constructor must be called.
The same happens with any class when you declare other constructor than default one. For example, having
public class A{
//no default no-arg ctor here
public A(String name){
....
}
}
public class B{
//default no-arg ctor will be created
}
so then
B b=new B();
A a=new A(); //// INVALID!
A a=new A("foobar"); // yeah that is it
The same applies when you are extending classes. To construct child instance, you must first "internally create parent instance" calling super.constructor. Since there is no default constructor, ANY of explicit declared superconstructors must be used.
When initializing an Object the constructor will always be called. Even if you do not define one constructor there will be a default one without any parameters. So if you define a constructor in the abstract class, you have to call that constructor with super().
If you do not define any constructors, then it will be implicitly called as the default one.
If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?
There is no default constructor available in AbstractClass since you define a parametrised constructor. If you don't define a constructor yourself, a default constructor without arguments is implicitly created. You can manually add such one now or you need to use the only available constructor (which is parametrised) with super().
Example of your code with defining constructor without arguments:
class AbstractClass {
AbstractClass() {} // added manually since not created implicitly
AbstractClass(int foo, float boo) {}
}
class RealClass extends AbstractClass {
RealClass() { } // calls super() implicitly
}
AbstractClass myClass = new RealClass();
Example of your code with calling super() with arguments:
class RealClass extends AbstractClass {
RealClass() {
super(1, 2);
}
}
class AbstractClass {
AbstractClass(int foo, float boo) {}
}
AbstractClass myClass = new RealClass();
Why do we explicitly write super() and call super class constructor. when compiler automatically adds super() as the first statement in subclass constructor?
Is this code
public class Sub extends Super {
public Sub() {
}
equivalent to this code?
public class Sub extends Super {
public Sub() {
super();
}
You need to call super if you are doing constructor overloading.
You need to use it if you are not using the default no arg constructor.
If you are using the default constructor and you are expecting it initialize based on a super class default constructor then there is no need to call super.
I'm reading java docs and reading about Constructors I got confused about the below paragraph.
You don't have to provide any constructors for your class, but you
must be careful when doing this. The compiler automatically provides a
no-argument, default constructor for any class without constructors.
This default constructor will call the no-argument constructor of the
superclass. In this situation, the compiler will complain if the
superclass doesn't have a no-argument constructor so you must verify
that it does. If your class has no explicit superclass, then it has an
implicit superclass of Object, which does have a no-argument
constructor.
What does mean that the compiler will complain if the superclass doesn't have a no-argument constructor
Reference: Java Docs
https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
Let's imagine a Base class such as
public class Base {
public Base(String s) {
}
}
Let's now create a subclass:
public class Sub extends Base {
}
That won't compile, because the above code is equivalent to
public class Sub extends Base {
// added by compiler because there is no explicitely defined constructor in Sub
public Sub() {
}
}
which is equivalent to
public class Sub extends Base {
// added by compiler because there is no explicitely defined constructor in Sub
public Sub() {
// added by compiler if there is no explicit call to super()
super();
}
}
The line super()tries to call the no-arg constructor of Base, but there is no such constructor.
The only way to have Sub compile is thus to explicitely define a constructor such as
public class Sub extends Base {
public Sub() {
super("some string");
}
}
By default every class has a no-argument constructor. If you create class A with a constructor with arguments, when class B extends A, you need to explicitly create a constructor which will call the super class constructor with arguments. Basically when you create a constructor, you lose the default call to the no-arg constructor (unless the constructor you created is still a no-arg constructor.
A constructor of the superclass and the subclass has to be called, implicitly or explicitly. Always.
If you provide a constructor for the subclass yourself, you can choose, which superclass constructor to call.
But if you don't provide a constructor for your subclass, Java creates a no-argument constructor for you. In that constructor it has to call a superclass constructor. But if there is no no-argument constructor in the superclass, Java cannot know which superclass constructor to call and which argument to use to do so.
class Superclass {
Superclass(String argument) {
//...
}
}
class Subclass extends Superclass {
// Implicit no-argument constructor, created by Java
Subclass() {
super(/* what String can Java put here? it cannot know it */);
}
}
Now, if there is a no-argument constructor of Superclass, Java can just call super(); in the default Subclass constructor.
Btw. that also happens automatically, if you define the Subclass constructor yourself and don't add an explicit call to a Superclass constructor. The Subclass constructor always calls a Supeclass constructor, be it explicitly or implicitly.
I read in scjp guide as following
In fact, you can't make a new object without invoking not just the
constructor of the object's actual class type, but also the
constructor of each of its superclasses!
For example
public class Person{
}
public class Employee extends Person{
public Employee(){
}
}
I don't create a Person instance but it is legal.
Please explain for me, thank for your help.
Whenever you instantiate a subclass, it'll call your superclass' constructor first.
You can find more about this here: JSL ยง8.8.7
Person.java
public class Person {
public Person() {
System.out.println("Super class constructor called");
}
}
Employee.java
public class Employee extends Person {
public Employee() {
System.out.println("Sub class constructor called");
}
}
If you then instantiate your Employee:
Employee e = new Employee();
Output:
Super class constructor called
Sub class constructor called
What they actually mean is
When you are creating a subclass object, i.e. its constructor is getting called, then superclass constructor gets callued internall
This is because for the default no-argument constructor there is a default super() call to the superclass constructor.
This goes on like the class hierarchy until the Object class.
In fact, if you do not write a no-argument constructor in superclass then the subclass declaration will throw compiler error.
public class Super {
public Super(int num){
}
}
public class Sub extends Super {
}
Here, class Sub will not compile giving the error Implicit super constructor Super() is undefined for default constructor because it cannot find a no-argument constructor in super class as the default no-argument constructor i.e. provided by compiler will have an implicit call to super().
Compiler provides a default no arg constructor only if there is no other constructor defined
As we have explicitly defined Super(int num), we will have to exlicitly create no-arg constructor as follows.
public Super(){
}
First, you don't have to create a parent instance (Parent) to instantiate a child class (Employee). You must have understood wrong.
Invoking the constructor of the parent class doesn't mean to create a new parent instance object (you're not calling it with new, so no new instance is created). You are creating a child instance, and for this, you need to first invoke the parent's constructor because of inheritance. Imagine for example the parent class has private fields that must be initialized in the constructor (for example private final fields). This fields cannot be accessed from the child class, but they can be initialized from the parent class constructor. You need to initialize this fields in the child instance, and the only way is calling super().
In this case Person has a default contructor which is invoked by default, no need to explicitly call it.
But in case Person has no default constructor, you need to call it explicitly. For example:
public class Person{
private final String name;
public Person(final String name) {
this.name = name;
}
}
public class Employee extends Person {
public Employee() {
}
}
This will not compile. You need to modify Employee so it calls Person constructor explicitly. For example:
public class Employee extends Person {
public Employee(final String name) {
super(name);
}
}
Superclass' nullary constructor is implicitly called.
Its because of constructor chaining:
First statement inside a any constructor by default is super();(This is a call to super class default constructor).
I don't create a Person instance but it is legal:
thats because you have a default constructor in Person class. So Employee class constructor can actually invoke super class constructor. Person()
Bottom line, the current class in which you are declaring a constructor, all the constructor upto the base class should be accessible via super(). If not, you have to explicitly make them accessible by explicitly making a call via super with proper parameters.
You have encountered one of the oddities of java.
If you don't define any constructors, the default, or "no args", constructor is implicitly defined. It's like invisible code.
If you define any constructor, args or no args, the implicit default constructor goes away.
To further compound the mystery, the first line of any subclass constructor must be to call a constructor of the super class. If you don't explicitly call one, the no-args constructor is implicitly called.