Construction Methods
A recent thread in ruby-talk reminded me of a change in the way I’ve been writing classes over the last year or so.
In the past, I used to enjoy the ability to overload constructors. To create a rectangle given two points, I might write:
Point p1 = new Point(1,1);
Point p2 = New Point(3,4);
= new Rectangle(p1, p2) rect
Alternatively, I might want to create a rectangle given one point, a width, and a height:
= new Rectangle(p1, 2, 3); rect
Inside class Rectangle, I’d have two constructors:
public Rectangle(Point p1, Point p2) { ... }
public Rectangle(Point p1, double width, double height) { ... }
The problem with this approach is that is breaks down when the different styles of constructor can’t be distinguished based on argument type. It also makes the code harder to read: if you see
new Rectangle(p, r, t);
where are the hints as to what’s going on?
So now when I write a class with multiple construction requirements, I tend make the constructor itself private, so it can’t be called outside of the class. Instead I use a number of static (class) methods to return new objects. These methods can have descriptive names (often with_xxx
, for_xxx
, or having_xxx
), and I don’t have to worry about parameter types. As a silly example, the following Ruby class has three constructor methods, letting me build a square by giving its area, its diagonal, or a side. What it won’t let you do is construct the object by calling new, as the constructor itself is private.
class Square
def Square.with_area(area)
Math.sqrt(area))
new(end
def Square.with_diagonal(diag)
/Math.sqrt(2))
new(diagend
def Square.with_side(side)
new(side)end
private_class_method :new
def initialize(side)
@side = side
end
end
= Square.with_area(4)
s1 = Square.with_diagonal(2.828427)
s2 = Square.with_side(2) s3
Of course this is nothing new to Smalltalk folks (nor is it particularly new or revolutionary elsewhere). However, it does seem to be less common than it should be in the Java world. Just because you can overload constructors doesn’t mean that it’s the best way to code your classes.