Skip to main content

Are constructors the enemy?

Posted by timboudreau on March 31, 2009 at 6:47 PM PDT

My friend Jon writes an interesting blog on the problem of constructors, and how a language might improve on them - and comes to a fairly startling solution.

duck.png
The major problems with constructors as I see it are

  • Especially in deep inheritance hierarchies, or when you inherit from a class in a library which could involve incompatibly, it is easy for your object to be called when it is in a not-fully-initialized state. We just had to do an update release, NetBeans 6.5 to deal with such a change in JDK 1.6_12 - this conversation shows the tip of the iceberg that crashed into NetBeans when changes from JDK 7 were backported - because of such a problem
  • A constructor ties you to the precise type of the object being constructed. As a library author, you get much more flexibility with a factory method, where you can return a subclass, possibly choosing which one based on an argument to the factory method. This makes it much easier to keep backward compatibility and guarantees your object is never exposed in a semi-initialized state (unless you're inheriting from something you don't control, which should be avoided when possible

Jon takes the exact opposite approach in his blog, suggesting running toward the problem - make semi-initialized objects the common case while eliminating constructors.

I don't know how realistic that would be for a language, but it is some interesting food for thought!

Related Topics >>

Comments

What's being suggested reminds me of ObjectiveC where you always have distinct allocation and initialization of objects. In a way ObjectiveC style init* methods are exactly the factory methods that you're suggesting which at least gives a precedent of this pattern being used in a real language.

And package default.

Disable calling public and protected functions in constructors. Problem solved?

> This is a good sample fo a pitfall: Indeed, I've fixed a lot of such bugs.

Even Josh Bloch agreed that he shouldn't have used constructors for the java collections library.

We all know that we must not call methods in a constructor body, which can be overridden. Why this should make constructors a bad thing per se? After all somehow somewhere the objects have to be constructed. Why not stop overestimating ourselves by thinking we are able to outsmart geniuses like Gilead Bracha or Joshua Bloch (or, looking at a different language, Bjarne Stroustrup) with a quick blog entry.

This is a good sample of a pitfall: public class Super { String value; // This class implements PropertyChangeSupport. setValue (String value) { firePropertyChange ("value", getValue(), this.value = value); } getValue () { return value; } } public class Sub extends Super { TimeZone tz = getCurrentTimeZone(); Sub () { super(); prepareListener(); // Create PropertyChangeListener. setValue ("Hello World: My Timezone is: "); } public propertyChange (PropertyChangeEvent pce) { if ( "value".equals (pce.getPropertyName() ) ) { System.out.println (getValue() + tz); } } } On propertyChange of "value" the TimeZone is null. This simple example is typical for big Java Beans with chaining Property Change Events. But IMHO you'll fall in the same trap with factories. Best regards, josh.