Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

NOT wanting to call the default constructor from child class

I am working on an animal class which needs a default constructor. I also need to extend the animal class with specific animals as well, with their own names and sounds.

My Animal class is as follows:

public class Animal {

public String name;
public String sound;

public Animal() {
    this.name = "animal";
    this.sound = "an animal makes a sound based on what animal that it is";
    System.out.println("I am an animal");
}
        
public void sound() {
    System.out.println("The " + name + " says " + sound);
}

After I wrote the other animal classes such as Sheep, pig and cow, I wrote a test class to verify if it was working. They’re carbon copies basically but here is the first one I wrote, the cow class:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

public class Cow extends Animal {
public String name = "Cow";
public String sound = "Moo";


public Cow() {
    System.out.println("I am a cow");
}
 

public void sound () {
    System.out.println("The " + name + " says " + sound);
}
    

}

My issue is that after making new "cows", or any of the other animals they all start out by saying "I am an animal" which is from the default constructor within the animal class and not needed. How can I avoid this? I was under the impression the default constructor would only be called when creating a new animal via Animal animal1 = new Animal(); but clearly, that is not the case.

I’ve been reading my textbook, looking over YouTube as well as here on Stack but to no avail.

Thought maybe I had to override something but I am not sure.

Here is my Test class and output:

public class Test {

public static void main(String[] args) {
    Animal animal = new Animal();
    animal.sound();
    Cow cow = new Cow();
    cow.sound();
                
}

}

Output:

I am an animal
The animal says an animal makes a sound based on what animal that it is
I am an animal
I am a cow
The Cow says Moo

Because I am actively trying to learn java I would very much appreciate being guided towards an answer, as well as an explanation to help me understand why this is happening.

>Solution :

The question why the superclass constructor is called, even without explicit super(); call is answered here. One of the constructors of the superclass must always be called. If the superclass has a (possibly implicit) default constructor then the super(); call from the subclass can be omitted, but the constructor is called implicitly. Your Cow constructor is the same as this one:

public Cow() {
    // Calls the `Animal()` superclass constructor
    super();
    System.out.println("I am a cow");
}

In your specific situation it might make sense to add an additional Animal constructor which takes the name and sound values as parameters and initializes the fields. If you still need a default Animal() constructor, you can have that delegate to the other constructor:

class Animal {
    public String name;
    public String sound;

    public Animal(String name, String sound) {
        // `this.name` refers to the field, `name` refers to the parameter
        this.name = name;
        this.sound = sound;
    }

    public Animal() {
        // Uses `this(...)` to call the other constructor
        this(
            "animal",
            "an animal makes a sound based on what animal that it is"
        );
        System.out.println("I am an animal");
    }

    ...
}

Note: If you don’t expect these fields to be reassigned, then you should make them final to protect against bugs and for thread-safety improvements.

Your subclasses can then call the Animal(String, String) constructor:

public class Cow extends Animal {
    public Cow() {
        // Calls the `Animal(String, String)` superclass constructor
        super("Cow", "Moo");
    }
}

This does not declare additional name and sound fields because the ones from Animal are inherited and accessible to Cow. Your current code for Cow actually introduces additional fields which hide the ones from Animal, see this answer.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading