It is not possible to call the supertype constructor directly - why not?

I have the following class examples in Java:

public class A { } public class Super { protected Super() { } public Super(A a) { } } public class Sub extends Super { } public class Consumer { public Consumer() { Sub sub = new Sub(new A()); //compiler error } } 

A compiler error indicates that the arguments cannot be applied to the default constructor in Sub, which is understandable.

What interests me is the rationale for this decision. Java generates an empty default constructor in Sub ; why can't he call it backstage in this case? Is this primarily a case of reasonable manual retention or is there a technical reason?

EDIT

I know this is a language restriction. I wonder why this is a language restriction.

EDIT 2

It seems that, as often happens, I was too close to the code I actually worked on to see the big picture. I gave a counter example in the answers below that show why this is Bad Thingยฎ.

+6
source share
5 answers

I think this is a problem of both readability and not suggesting intent. You speak

Java generates an empty default constructor; why can't he call it backstage in this case?

However, for me it would be far more sensible for Java to implicitly call the Super(A) constructor behind the scenes than to call the Super() constructor without paying attention to A

And you have it. We already have two disparate assumptions about what should (or may) happen in this case.

One of the basic principles of the Java language is transparency. As much as possible, the programmer should be able to see, looking through the code, what will happen, sometimes due to convenience or magic at the syntax level.

The parallel principle does not imply intent: in cases where the programmer's intentions seem ambiguous, the Java language sometimes prefers a compilation error, and does not automatically use the default value using some (arbitrary or other) selection algorithm.

+2
source
 public class Sub extends Super { } 

does not have a Sub (A a) constructor; it only has a default Sub () constructor.

Constructors are not inherited.

+2
source

Base classes must call superconstructors to provide a proper instance of the object. For example, consider:

 class Super { final String field1; public Super(String field1) { this.field1 = field1; } ... } class Base extends Super { final String field2; public Base(String field2) { this.field2 = field2; } ... } 

Base constructor overrides Super constructor? If so, then field1 will no longer be guaranteed to be initialized, which will cause the inherited methods to act unexpectedly.

The moment you add a non-default constructor to a subclass, then the inherited constructors stop working. I think it would be a confusing and rarely useful feature that it added to the language, although technically I see no reason why this would not be possible.

+2
source

You have redefined the default public constructor, so there is nothing to name.

So, the class Sub is equivalent

 public class Sub extends Super { protected Sub(){} public Sub(A a) { } } 

This is because his

  • Behavior in strict mode - behaves as specified by the programmer, and it also follows the concept of inheritance in OOP languages.
  • Following its legacy of C ++
0
source

I see this as the technical reason for this behavior; I agree with several other answers that this can be semantically confusing.

Consider the following example:

 public class A { } public abstract class Super { protected Super() { // perform time consuming, destructive, or // otherwise one-time operations } public Super(A a) { this(); // perform A-related construction operations } } public class Sub extends Super { } public class Consumer { public Consumer() { Sub sub = new Sub(new A()); } } 

When building Sub in this case, the default constructor on Sub will be called, which will be bound to the default constructor on Super (because this magic defines the language). Then, calling Super(A) will invoke logic designed to run once during construction. This is clearly not what the developer intends.

Even without calling this() in the Super(A) constructor, the intent of the developer cannot be determined; for any reason, constructors can be mutually exclusive.

0
source

Source: https://habr.com/ru/post/900006/


All Articles