Hello. I study OOP with Java and came across such a rake: I have a class Animal. It has only one name variable. When creating an Animal object, a constructor is called, which displays the message "A new animal is created. Its name is name.". Next, I created a Cat class that inherits from Animal and I want it when I do this Animal cat = new Cat("Кошка"); I got the message “A new cat was created. Its name is name”. I'm trying to do it in the Cat class constructor, but he swears, he says, you can only

 public Cat(String name) { super(name); } 

But I do not want that. Is it possible to override the constructor in the child class? Or is it nonsense and need to act differently? Full code below.

 public class Main { public static void main(String[] args) { Animal animal = new Animal("Лео"); Animal cat = new Cat("Кошка"); } } public class Animal { private String name; public Animal(String name) { this.name = name; System.out.println("Новое животное создано. Его имя: " + this.name); } } public class Cat extends Animal { public Cat(String name) { super(name); } } 
  • Add a constructor with no arguments to the Animal class, then you can override without calling the constructor from the parent class - Artem Konovalov
  • @ArtemKonovalov Then I can not give the names of animals when creating - Ivan Blohin
  • @IvanBlohin Тогда я не смогу давать имена животным при создании what is this statement based on? - Alexey Shimansky
  • then how do you want to create a cat without a name? - Artem Konovalov
  • @ArtemKonovalov corrected the wording of the question. And tell me, for one thing, please, what is the difference Animal Cat = new Cat ("Cat"); Cat cat2 = new Cat ("Cat 2"); ? The output is the same - Ivan Blohin

4 answers 4

The fact is that the default constructor (which is without parameters) on the child class automatically invokes the same constructor on the parent class.

Those. two entries

 public class Person { public Person() { } } public class Employee extends Person { public Employee() { } } 

and

 public class Person { public Person() { } } public class Employee extends Person { public Employee() { super(); } } 

will be identical.

However, there are still rules associated with constructors.

first rule:

If no constructor is specified in the class, the compiler will generate a default constructor for you ... i.e. if you write like this:

 public class Person { } 

then all the same in the end we get

 public class Person { public Person() { } } 

But (!!!) , however, the second rule:

if you make at least one constructor with parameters, then the compiler does not generate a default constructor.

Hence the conclusion:

  • In the parent class, you have a constructor with parameters (not the default), which means the compiler does not generate the default constructor itself.
  • The class successor with the default constructor will look for the default constructor in the parent, but it is not there (see the first paragraph why)
  • Correspondingly, in order to do something in the default constructor of the heir, you need to define the default constructor of the parent.

roughly speaking

 class Animal { public String name; public Animal() {} public Animal(String name) { this.name = name; System.out.println("Новое животное создано. Его имя: " + this.name); } } class Cat extends Animal { public Cat(){ System.out.print("Была создана новая кошара."); } public Cat(String name) { this(); System.out.println(" Имя кошары " + name); } } 
  • one
    Wow, everything is interesting. Thank you very much, now I’ll understand it better. And the difference Animal cat = new Cat ("Cat"); Cat cat2 = new Cat ("Cat 2"); do not tell me? I was answered a little lower and, as I understood, if I write the first option, everything available to me is what I wrote in Cat and Animal, and if the second one, then only what I wrote in Cat, and the variables and methods of the Animal class not available? - Ivan Blohin
  • @IvanBlohin, did not understand - Grundy
  • Why protected ? let private remain if with him all the work through methods Animal - Grundy
  • @Grundy if only this way ... although if it is different, then you need to call super. And if you call super, then you can't call this ....... Aaaaaaaa, shoot me)) - Aleksey Shimansky

What prevents to add in the constructor of the descendant class the conclusion of what was created:

 public Cat(String name){ super(name); System.out.println("создана кошка!"); } 

Alternatively, you can make Animal abstract and define the abstract getName() method in it, then you can do without any constructor overrides.

  public Animal() { System.out.println("создана "+getName()); } protected abstract String getName(); 

    As you already understood from the previous answers, it is impossible to override the parent constructor. By calling a constructor, you call the parent constructor chain. In general, it is recommended to use methods called setters to set the values ​​of object fields. That is, void setName (String name). If you need to be sure when you create an object to assign a name. It is better to call the setName method in the constructor. However, when inheriting, this method will have access to the parent variable. In general, Animal is better to make an abstract class or interface.

      "And the difference is Animal cat = new Cat (" Cat "); from Cat cat2 = new Cat (" Cat 2 ");" - if you learn OOP, then this topic is already Polymorphism. In short, classes, as you remember, these are structures (data types) with methods. As Bruce Ekkel says in java philosophy - ".. Everywhere you see a class, understand the type and vice versa" By creating classes you create your own data types. You have created 2 data types, Animal and Cat. The first cat variable is Animal, and the second cat2 is Cat. But since the Cat class is a descendant of the Animal class, we can use polymorphism. In short, polymorphism is “the ability to work with several types as if it were the same type and at the same time the behavior of each type would be unique depending on its implementation.” For example, you may have different descendants of Animal - Dog, Fox, Wulf, Bair, etc., and all of them can be declared and processed as Animal. For example, create an array of Animal animals [] and store instances inside and Dog and Fox and anything that is (extends) Animal.

      • wrote here because the answer did not fit into the comment - Mr.Ki.D.
      • Aha There it is like. 5 minutes ago I stumbled upon Jacob Fine's channel, I watch a video on this topic, thank you) I heard about polymorphism before, but I thought that I would not stumble soon, but it was very close .. - Ivan Blohin
      • In fact, do not dwell on the theory without practice. Do not always like these examples of abstract Animal. The use of inheritance (extensions or implementations) is already a matter of architecture. You are unlikely to design the Animal class. Also I can advise you the book Philosophy of Java. must read for java programmer. - Mr.Ki.D.