Let's say you want to have an Angle class, which holds radians internally but can be initialized with degrees or radians.
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:
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:
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.