Calling super() - [OOP & Java #12]
Tags: computerscience, java
Published: 2021-02-26 01:31:34

P.S. Finally back with another quick article on something that I learned during (yet another) late-night discussion.

### Motivation
While browsing through the codebase of a brownfield project that I am currently working on as part of my school work, I found the following lines weird at a glance. 
```java
public class StorageManager implements Storage {
    // other details omitted ...
    /**
     * Creates a {@code StorageManager} with the given {@code AddressBookStorage} and {@code UserPrefStorage}.
     */
    public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) {
        super();
        this.addressBookStorage = addressBookStorage;
        this.userPrefsStorage = userPrefsStorage;
    }
```
The above code belongs to a concrete implementation of an interface named `Storage` and the particular line that I was interested in is this: `super();`.

Reasons why I felt that the call to super was unusual:
1. `StorageManager` does not extend from any parent class, so I supposed calling super means calling the `Object` constructor, why would one ever do that?
2. If somehow the call to super is related to the interface that `StorageManager` is implementing, it makes no sense because interfaces cannot be instantiated anyway.
3. While I knew that calling super invokes the parent constructor and one could use it to pass relevant parameters up to the parent, I see no practical purpose in the above code.

---

### Discussion
I posted my question in the class forum and was able to get some helpful responses. So the first thing I did to follow up was to try to remove the `super();` to verify whether it has a practical purpose. Tests were still passing and no observable issues when I 
restart the application. That proved a point: the call to super, in this case, was unnecessary and meaningless.

I was going to conclude with the above fact and also the practical tip of always testing out code to verify my suspicions. However, my professor's followed up comment intrigued me. Particularly, this line below did not make sense to me:
> An explicit call to super(...) is needed only if the parent class doesn't have a parameter-less constructor or ...

I was unsure what the above statement was referring to and with the help of a few fellow students who joined the discussion, and some more Googling, I finally understood the statement. This was the epitome of not knowing what I don't know.

---
### Analysis
In order to understand the above statement, we need to know the following facts, which I extracted from the references included at the end of this article.

- If no constructor is defined in a class, Java compiler automatically create a no-argument (no-arg) constructor, that simply issues a super() call. That is:
```java
public class Foo {
}
```
is equivalent to 
```java
public class Foo {
  Foo() {
    super();
  }
}
```
---
- The default no-arg constructor will not be automatically generated, if one (or more) constructor was defined. In other words, you need to define the no-arg constructor explicitly if other constructors were defined. That is:
```java
public class Foo {
  int bar;
  Foo(int bar) {
    this.bar = bar;
  }
}
```
does **not** become the following by default:
```java
public class Foo {
  int bar;
  Foo(int bar) {
    this.bar = bar;
  }
  Foo() {
    super();
  }
}
```
---
- If the immediate superclass does not have the default constructor (it defines some constructors but does not define a no-arg constructor), you will get a compilation error in doing a super() call. That is:
```java
public class Foo {
  int bar;
  Foo(int bar) {
    this.bar = bar;
  }
}
```
if the above is the `Foo` class, then the following will cause compilation error:
```java
public class Bar extends Foo {
  Bar() {
    super();
  }
}
```
Or this:
```java
public class Bar extends Foo {
  Bar() {
  // some lines as long as they are not super
  }
}
```
Or this:
```java
public class Bar extends Foo {
  // no constructor provided
}
```
The only valid way is something like this:
```java
public class Bar extends Foo {
    Bar() {
    super(10);
  }
}
```

- The explanation to the above: Java guarantees that the constructor method of a class is called whenever an instance of that class is created. It also guarantees that the constructor is called whenever an instance of any subclass is created. In order to guarantee this second point, Java must ensure that every constructor method calls its superclass constructor method. Thus, if the first statement in a constructor does not explicitly invoke another constructor with this() or super(), Java implicitly inserts the call super(); that is, it calls the superclass constructor with no arguments. If the superclass does not have a constructor that takes no arguments, this implicit invocation causes a compilation error.

---
### Final example
To summarize, I will do a walkthrough of another example from a StackOverflow post:
```java
public class Base {
   public Base(int foo) {
   }
}

public class Subclass extends Base {
   public Subclass() {
      super(15);
   }
}
```
If the constructor of `Subclass` does not include the `super(15)` call, Java will implicitly insert `super()` as the first line of the `Subclass` constructor, which will cause a compilation error in the case where the `Base` class does not have a parameter-less constructor(`Base()`), which unfortunately will not be automatically generated because there is an existing constructor(`Base(int foo)`).

---
### References
- [Java Programming Tutorial](https://www3.ntu.edu.sg/home/ehchua/programming/java/J3b_OOPInheritancePolymorphism.html#zz-2)
- [3.4. Subclasses and Inheritance docstore.mik.ua/orelly/java-ent/jnut/ch03_04.htm](https://docstore.mik.ua/orelly/java-ent/jnut/ch03_04.htm)
- [Calling super()](https://stackoverflow.com/questions/2632882/calling-super)