Reverse superclass envy and bad mental pointers

I’ve ranted previously about Python and made promises of future posts about why Ruby is so much cooler. It really is and the topic of this article covers one of the common idioms used by most Ruby folks who may have taken a shot at their own domain specific language in Ruby. The following is one of the really useful idioms but apparently not a very well understood or well explained one for Ruby coders.

To many Ruby folks this is the vague-but-really-really-cool-idiom that is

class << self; self; end;

This is used a lot in the Rails framework. You shouldn’t have to look very deep into the Rails source code to find it. As an example I’ll guess that most Ruby coders are familiar with Why’s example for Dwemthy’s Array that explains the idiom.

Here’s the relevant bit of example code:

class Creature
  def self.metaclass; class << self; self; end; end
  
  ... more code for meta-programming goes here ...</p>

<p>  traits :life, :strength, :charisma, :weapon
end

This then allows the definition of other classes derived from the Creature class such as these for our example:

class GreenMonster < Creature
  traits :greenness, :scariness
  life 90
  strength 45
  charisma 23
  weapon 80
  greenness 10
  scariness 12
end</p>

<p>class RedMonster < Creature
  traits :redness, :loudness
  life 75
  strength 50
  charisma 90
  weapon 65
  redness 20
  loudness 33
end

It seems that when it comes to understanding how this idiom works most of the confusion has to do with misnaming the key feature used in the Creature class, specifically the ‘metaclass’ in the code above. It’s usually called a meta-class(as in our example), shadow-class or class-object-instance-singleton , yikes!. (Adding in the additional popular belief that Ruby classes behave like objects can make this even more difficult to grasp. They do behave like objects but they technically are not like most objects in Ruby).
Technically the ‘metaclass’ is a singleton for each derived class we have but this is not as important (and probably best ignored for now) as defining what the ‘metaclass’ really is in terms of object-oriented meaning.

Here I offer my attempt at another simple explanation:

The idiomatic line of code is merely a hack to obtain access to the sub/derived/child class (correct OO nomenclature).
In Ruby, classes have access to their parent class via the ‘superclass’ method.
The equivalent method to go the other direction i.e. ‘subclass’ would be very useful but because there is no such method the following hack is required.
The scope that is accessible to the code between the class << self ... end block has access to the derived class scope and so 'self' is returned from the block which is then returned from the parent class method 'self.metaclass'. 'self' is the sub-class derived from Creature. In our example it's either the GreenMonster or RedMonster class.

There is no magic in this idiom when this little expletive is made clear but the way it’s usually explained and the popular naming seem to be the main source of confusion.
Once you look at this for what it is, there’s nothing magic except for the popular names applied to it. Maybe we should start using the more informative/explicit sub/child class naming and leave out the explanation of classes behaving as objects when explaining this useful idiom ?

or maybe that’s just me in the corner, in the spotlight…

This entry was posted in Uncategorized by jng. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *