From: Florian Frank Date: 2007-03-22T06:06:38+09:00 Subject: Re: does Ruby not support multiple "initialize" methods for a class??? Chad Perrin wrote: > I've heard it said -- and I tend to agree -- that regular use of > "patterns" is a sign that the language lacks something. I wonder if > that is the case with Ruby, as applies to multiple constructor behavior > implementation. > I don't consider this to be a pattern, I consider overloading constructors an anti-pattern. One of the few good Java books (among all the mediocre or even worse ones) is "Effective Java" by Joshua Bloch: http://java.sun.com/docs/books/effective/toc.html In the first chapter (actually chapter 2) in the first item Bloch advises Java programmers to consider using static factory methods instead of public and/or overloaded constructors. He lists the following advantages: : One advantage of static factory methods is that, unlike constructors, they have names. : If the parameters to a constructor do not, in and of themselves, describe the object being : returned, a static factory with a well-chosen name can make a class easier to use and the : resulting client code easier to read. : [...] The same is true in Ruby, if you use class methods (methods of a class's eigenclass). The workarounds in the initialize method even *look* code smelly. In Java overloading a constructor once or twice doesn't seem to be such a bad idea. But other programmers tend to just copy and paste another constructor below the others. Once you have a class that comes into the two digit range of constructors, it gets quite difficult to remember all the different possible permutations of types. (Yes, I had to maintain code like that.) And I think, overloading in general isn't such a good idea either. It can lead to really funny semantic errors, if it teams up with Java's numeric type promotion for example. (Yeah, this happened to me, too.) : A second advantage of static factory methods is that, unlike constructors, they are not : required to create a new object each time they're invoked. This allows immutable classes : (Item 13) to use preconstructed instances or to cache instances as they're constructed and to : dispense these instances repeatedly so as to avoid creating unnecessary duplicate objects. This is an advantage in Java only, in Ruby "constructors" already have this advantage, the are actually factory methods - and classes are nothing but object factories, objects that can make other objects. Ruby doesn't have "real" constructors like Java has. In Ruby a "constructor" is a simple method, defined in class Class and thus can be shadowed by defining a method in a class's eigenclass, where new objects can be allocated, configured, cached, and so on. These changes are also transparent for client code, which doesn't have to be changed to, e. g., profit from caching. : A third advantage of static factory methods is that, unlike constructors, they can return : an object of any subtype of their return type. This gives you great flexibility in choosing : he class of the returned object. This is a Java advantage only, because Ruby doesn't have to work around a rigid type system. You just have to take care not to screw up. : One application of this flexibility is that an API can return objects without making their : classes public. Hiding implementation classes in this fashion can lead to a very compact API. : This technique lends itself to interface-based frameworks, where interfaces provide natural : return types for static factory methods. Can be done in Ruby as well for both "new" factory methods or better named factory methods. : The main disadvantage of static factory methods is that classes without public or : protected constructors cannot be subclassed. : [...] This isn't a disadvantage in Ruby, because private methods *can* be called from subclasses. : A second disadvantage of static factory methods is that they are not readily : distinguishable from other static methods. They do not stand out in API documentation in : the way that constructors do. Furthermore, static factory methods represent a deviation from : the norm. Thus it can be difficult to figure out from the class documentation how to instantiate : a class that provides static factory methods instead of constructors. This disadvantage can be : reduced by adhering to standard naming conventions. This might be a disadvantage, but you should choose meaningful names for all methods and document accordingly anyway. -- Florian Frank