dagfinn | 02 May, 2008 23:05
Everybody who writes object-oriented code knows about constructors. You need them so the program knows how to instantiate objects, right? And you especially need them when a lot of things have to be done while instantiating an object. And personally, I've never considered visibility restrictions important enough to be a major argument against those languages that have lacked them (PHP 4). So why would I be skeptical of public constructors?
I got the idea after reading Joshua Kerievsky's book Refactoring to Patterns. One of his refactorings is called Replace Constructors with Creation Methods. In Java, unlike PHP, you can have multiple constructors that are distinguished only by the number and type of arguments. That may be practical sometimes, but as Kerievsky's example shows, it be more readable to have creation methods with different names instead. Which is what you have to anyway in PHP.
But why not take this one step further and do it even when there is only one constructor? For example, here's an ultra-basic Redirect class:
class Redirect { private $url; public function __construct($url) { $this->url = $url; } public function execute() { header("Location: ".$this->url); exit; } }
This may seem simplistic, but it is the kind of class I might actually use at an early stage in the development of a web application. Anyway, we can apply what is essentially the same process as Kerievsky's by adding a creation method whose name is somewhat more telling than __construct().
class Redirect { private $url; public function __construct($url) { $this->url = $url; } public static function withUrl($url) { return new self($url); } public function execute() { header("Location: ".$this->url); exit; } }
Now all that remains is to make the constructor private.
private function __construct($url) { $this->url = $url; }
Is this an improvement? The additional code might be considered unnecessary complexity, or in a word: clutter. On the other hand, our client code might seem more readable when it looks like this:
$redirect = Redirect::withUrl("http://www.example.com/index.php"); $redirect->execute();
Instead of:
$redirect = new Redirect("http://www.example.com/index.php"); $redirect->execute();
You could object that it's fairly obvious anyway in this example that we're inputting a URL. But if the URL string is supplied as a variable or method call instead of a plain string, it would be less obvious.
No doubt there are many cases in which a plain constructor is the best choice, but I think this is worth considering.
| « | May 2008 | » | ||||
|---|---|---|---|---|---|---|
| Su | Mo | Tu | We | Th | Fr | Sa |
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |