What's wrong with overridable method calls in constructors?

Viewed 138014

I have a Wicket page class that sets the page title depending on the result of an abstract method.

public abstract class BasicPage extends WebPage {

    public BasicPage() {
        add(new Label("title", getTitle()));
    }

    protected abstract String getTitle();

}

NetBeans warns me with the message "Overridable method call in constructor", but what should be wrong with it? The only alternative I can imagine is to pass the results of otherwise abstract methods to the super constructor in subclasses. But that could be hard to read with many parameters.

8 Answers

I certainly agree that there are cases where it is better not to call some methods from a constructor.

Making them private takes away all doubt: "You shall not pass".

However, what if you DO want to keep things open.

It's not just the access modifier that is the real problem, as I tried to explain here. To be completely honest, private is a clear showstopper where protected usually will still allow a (harmful) workaround.

A more general advice:

  • don't start threads from your constructor
  • don't read files from your constructor
  • don't call APIs or services from your constructor
  • don't load data from a database from your constructor
  • don't parse json or xml documents from your constructor

Don't do so (in)directly from your constructor. That includes doing any of these actions from a private/protected function which is called by the constructor.

Calling an start() method from your constructor could certainly be a red flag.

Instead, you should provide a public init(), start() or connect() method. And leave the responsibility to the consumer.

Simply put, you want to separate the moment of "preparation" from the "ignition".

  • if a constructor can be extended then it shouldn't self-ignite.
  • If it self-ignites then it risks being launched before being fully constructed.
  • After all, some day more preparation could be added in the constructor of a subclass. And you don't have any control over the order of execution of the constructor of a super class.

PS: consider implementing the Closeable interface along with it.

Related