Named constructors

JN 666total at wp.pl
Sat Nov 9 00:02:52 UTC 2024


Let's say you want to have an Angle class, which holds radians 
internally but can be initialized with degrees or radians.

```d
class Angle
{
     float radians;

     this(float rad) : radians(rad) { }
     this(float degs) : radians(degs * (PI / 180.0f)) { }
}

Angle a = new Angle(90.0f);
```

Won't work, because you can't have two constructors with same 
args. Of course you can work it around by e.g. wrapping them in 
some "Degree" and "Radian" struct so that they're separate type 
and overloads.

Next option, static factory methods:

```d
class Angle
{
     float radians;

     // hide constructor so that users use the factory methods
     private this(float rad) { radians = rad; }

     static Angle fromRadians(float rad) { return new Angle(rad); }
     static Angle fromDegrees(float degs) { return new Angle(degs 
* (PI / 180.0f)); }
}

Angle a = Angle.fromDegrees(90.0f);
```

This works, but is awkward because suddenly you don't use the new 
keyword and it's not immediately obvious that these methods are 
meant to be used for construction of the object. After typing 
"Angle." an IDE will suggest all static methods on the class 
which can be a long list.

Named constructors to the rescue:

```d
class Angle
{
     float radians;

     this.fromRadians(float rad) : radians(rad) { }
     this.fromDegrees(float degs) : radians(degs * (PI / 180.0f)) 
{}
}

Angle a1 = new Angle.fromRadians(PI / 2.0f);
Angle a2 = new Angle.fromDegrees(90.0f);
```

Much clearer for the user, user can type "new Angle." and the IDE 
would suggest only constructors instead of all of the static 
methods on the class. Assumption would be that if named 
constructors exist, there is no implicit argumentless constructor 
so Angle a3 = new Angle() won't work anymore.


More information about the dip.ideas mailing list