Class Methods

In my last post I wrote that providing a home for class methods was the raison d’être of the Metaclass. So why go through all the trouble? What are class methods good for? Four uses worth exploring are Object Creation, Annotations, DSL’s, and removal of structural duplication

This post is about Ruby class methods and not Ruby static methods. There is a good reason for this. There are no static methods in Ruby.

In Java and C# “static method” and “class method” are synonyms, with “static” indicating that the methods are statically bound. What does it mean for a method to be statically bound? Consider a normal (non-static) instance method in Java. Client code that consumes the method doesn’t know at compile time what method body will be associated with that usage. It may be the instance method defined on the class, but it may just as well be an overridden version of the method defined in a subclass. The method implementation must be “dynamically bound” to the invocation at runtime. The compiler doesn’t have this issue with class methods, as in Java and C# class methods cannot be overridden. Classes methods in Java and C# are not invoked on class instance, but are rather scoped to the class name. As class method references can only resolve to one location, the compiler can “bind” the reference once at compile time “statically”. Classes methods in Ruby are normal instance methods stored on the class’s Metaclass. Even if Ruby were a compiled language, there would be no way to know at compile time which implementation of a method would eventually be responding to a message passed to a class object at runtime.

In any OO language, the most common use of class methods is for object creation. Every Ruby programmer is familiar with the primary object creation class method, new. Most programmers have also had cause to define alternative class methods for instantiating an object. In “Effective Java”, Joshua Bloch enumerates the advantages of this sort of factory method. These advantages are wholly applicable to Ruby.

Class methods have names

Java requires all method signatures to be unique. Suppose a Java programmer wants to allow the instantiation of an object in two different ways. Both instantiation methods rely on a boolean and an int parameter. One way to solve this is to define two constructors…

This is valid Java, but it’s just a wee bit hackish to be overloading methods based on the order of their parameters. Consumers of the class must infer the difference between the two constructors from the parameter names or a reading of the source. In Ruby this problem is more acute, firstly because of duck typing, and secondly because Ruby has no facilities for method overloading. For example, consider a Ruby class defined as…

The second definition of initialize completely replaces the first definition. Hacked up solutions to this type of problem aren’t relegated to the Java world. In fact, duck typing allows for some horribly creative solutions in Ruby. WARNING! Don’t do this…

or this…

or this…

Instead strongly prefer…

For an in the wild example of a factory class method in Ruby, look no further than ActiveRecord:Base.create

Class methods don’t have to return a new object

Sending the new message to a class will always cause the interpreter to create a new instance of the class. This occurs in rb_class_new_instance, the function bound to the new method of Object.

rb_class_new_instance calls rb_obj_alloc to allocate a new object which is handed off to the initialize method by rb_obj_call_init. As an interesting side note, notice that you can avoid having the initialize methods called by instantiating objects by calling SomeClass.allocate which returns the return value of rb_obj_alloc.

Sometimes a new object is not required, but rather a reference to an instance from a pool of existing objects. Database connections are one common example. Class methods are an excellent solution to the problem of how to provide access to the instance pool. When the available pool of instances is limited to one object, this solution is an implementation of the Singleton Pattern. “Singleton” here refers to the OO pattern documented in Design Patterns by Gang-Of-Four, not the Ruby specific Singleton class.

The Ruby Standard library includes a Singleton module to take the work out of implementing this pattern. The source includes extensive documentation on the implementation, so I won’t cover it here. Suffice to say that the module adds a class method, instance to the including class.

Why have this module at all? The Ruby language already provides a facility for creating objects with only one instance, classes. Why not define a singleton as a class…

The interpreter guarantees that there will only ever be one instance of Foo’s Metaclass, the Foo class itself. The existence of metaclasses means this question is applicable to Smalltalk as well. In “The Design Patterns Smalltalk Companion” by Sherman R. Alpert, Kyle Brown, and Bobby Wolf, two cases are made against implementing the Singleton Pattern with class methods. The first is conceptual. Classes should not be domain objects, their role is to allow for accessing and instantiating domain objects. Defining domain logic directly in classes is a perversion of this intent. The second argument is pragmatic. If a requirement is introduced that requires the usage of multiple instances of the formally singleton object, the refactoring away from class method calls is more laborious then a traditional Singleton pattern implementation. Although ‘The Design Patterns Smalltalk Companion” is a valuable read for Ruby programmers, in this case I don’t find the arguments particularly compelling . Class methods probably are the simplest thing that could possible work when Singleton Pattern like functionality is needed.

Class methods can return subclasses

A classic usage of factory methods is to return a subclass of the class receiving the message based on an input parameter. This is good encapsulation, as the consumer of the class does not need to know the details of which subclasses exist and which is appropriate for it’s needs.
If one is fortunate enough to have useful conventions in place, a bit a metaprogramming can make this usage particularly powerful. For example instead of …

one could implement by_nationality as…

Not only is this implementation more succinct, it extensible to handle any Pirate nationality that follows the convention. Keep in mind that classes aren’t the only place to store behavior. Class methods might return a new instance of the class with modules mixed in…

Perhaps even more powerful, a class method might alter the Singleton class of an instance before retuning the object. This is essentially subclassing on the fly. Suppose Pirate’s have fighting behavior. A class method could be created to return a pirate with a customized fighting style…

Even further out on the metaprogramming ledge, the consumer could define the fighting style directly…

This last example, while interesting, doesn’t strike me as good style. The consumer knowing both that it needs a Pirate to fight, and the implementation details of that fighting style seems like an awful lot for the consumer to know.

That covers using class methods for object creation. I’ll be covering class methods usage for annotations, DSL’s, and removal of structural duplication in the next post(s). As always thanks for reading. I’m always happy to get your feedback, inquiries, corrections, and criticism.

Thanks to John Hume for contributing his insight and expertise to this post.

2 Responses to “Class Methods”

  1. Rick Bradley

    Patrick,
    Thanks for a very interesting read.

    I’ve often wondered why Ruby programmers who feel the need to use the Singleton (or Multiton, for that matter) patterns, don’t simply change Foo.new to check a pool (@@pool), and for new objects call obj = Foo.allocate, and obj.initialize(args), pushing obj into @@pool, and returning obj.

    BDD-wise the behavior we want isn’t usually of concern to the caller, but it is of concern to the Foo class. It’s a creation-time behavior so it is definitely in the realm of the constructor. Unlike Java, .new is a class method rather than an operator. Just take over .new and implement the Singleton behavior there where it belongs.

    Why should client code have to call Foo.instance, e.g., and be aware of something that should be encapsulated in Foo. If the Singleton behavior needs to change, the .new method changes (or the override is simply taken out), and no client code has to be touched.

    I wonder if not taking advantage of Ruby in this way is just a too-literal reading of the popular Java implementation of GoF patterns carried along in a “Cargo Cult” manner.

    Best,
    Rick

  2. pfarley

    Hi Rick. Sorry it took a while to get back to you on this and thanks for the comment. It’s an interesting point about managing the pool through new. I also cringe when I see GoF patterns copied verbatim into Ruby as if the “best” C++ solutions are the “best” Ruby solutions. That said, I think encapsulation veers uncomfortably close to misleading when a method called new does not actually return something that is new. The nice thing about “instance” or similar is that it’s not promising you anything… maybe it’s new, maybe it’s from a pool, the only thing it suggests is that it is an instance of what you asked for.