Jonathan Boccara's blog

Strongly typed constructors

Published December 5, 2016 - 8 Comments

This is the first post of a series on the topic of expressive types, that is, types that express what they represent, rather than how they are implemented. By carrying meaning, these types improve the readability and safety of the code.

Here is the series about strong types:

 

Motivation

You may have come across the situation where an object needs to be constructed in two different ways, but with the same type. As an illustration let’s take the example of a class modelling a Circle.

Say that this class has the responsibility of providing its circumference and area, and can be constructed with its radius:

 

Now we want to add the possibility of providing the diameter to the circle instead of the radius.

The diameter is represented by a double, like the radius, and here comes the issue with the constructors: there would be 2 constructors with the same prototype, that is, taking a double:

This is not valid code, because calls to the constructor become ambiguous:

Note that we don’t have the same issue with setters:

The above setters are not ambiguous, because setters carry a name (setRadius and setDiameter). The point of this post is to show you how to make constructors carry a name too.

Tag dispatching: not the best option

Some pieces of code solve this issue with tag dispatching. If you’ve never heard of tag dispatching you can just skip through to the next section. Otherwise you may want to read on, to understand why this is not the best option here.

The idea of tag dispatching is to add a parameter to each prototype, in order to disambiguate the calls. Each prototype would get a parameter of a different type, making them distinguishable at call site. The additional type doesn’t carry a value. It is just there to specialize the prototypes. Therefore, new artificial types are created, with neither behaviour nor data, such as:

The constructors would then become:

And at call site:

I see 2 drawbacks with this technique:

  • it makes the syntax arguably more awkward,
  • it doesn’t scale. If you have several constructors with several arguments you need to disambiguate, prototypes become bigger and bigger.

Carry meaning in the type

A better alternative is to use a more expressive type. When you think about it, what you really want to pass to the constructor is a radius (or a diameter). But with the above implementation, what you are actually passing is a double. True, a double is how a radius is implemented, but it doesn’t really say what it is meant to be.

So the solution is to make the type expressive, that is to say to make it tell what it represents. This can be done by building a thin wrapper around the type, just for the purpose of putting a label over it:

And similarly, for diameter:

Then the constructors can use them this way:

And at call site:

Now, the two wrappers we wrote are very similar and scream for generalization, and this is the topic of the next post: strong types.

Related articles:

Share this post! Facebooktwittergoogle_pluslinkedin    Don't want to miss out ? Follow:   twitterlinkedinrss

Receive regular updates to make your code more expressive.