Sometimes software jargon gets in the way of understanding what practical use something is. For example, you have a problem and you want to know how to solve it so where do you look it up in the ruby book?
What I am going to describe is based on the concept of 'metaclasses' which are classes for creating classes. If that jargon fried your brain then lets have a problem and an example.
I want to create classes for implementing Commands. Each Command class has a command number and I want to define this Command Number in the class definition but I don't want to wear my fingers out typing them in. What nice syntactic sugar can ruby offer to help me with this?
1 # 2 # Class for building command classes 3 # 4 class Command 5 class << self 6 attr :nCommandNumber 7 8 def CommandNumber( nNumber) 9 @nCommandNumber = nNumber 10 end 11 end 12 end
Ok, horrible syntax so what on earth is going on here? Well the effect of 'class << <object>' is to add new methods to an object so in this case we are adding a new attribute 'nCommandNumber' to hold our command number and a new method 'CommandNumber' so set its value to an object referred to by 'self'.
So what is 'self' equal to? Well it turns out that when you use this class (Command) to create another class (ACommand) then 'self' will hold the value of the 'ACommand' class object, i.e. the object that creates instances of ACommand objects.
# # Declare a specific command # class ACommand < Command CommandNumber 123 end
Hum, that looks easy. When ACommand is being defined the line 'CommandNumber 123' will result in the CommandNumber method in Command being executed on the ACommand class object so 'ACommand' will have an attribute called nCommandNumber added to it. We can see whether this happened with:
print ACommand.nCommandNumber =>123
and indeed it works sweetly (which is what you would expect from syntactic sugar). It is important to note that it is the ACommand class itself that has these attributes, NOT objects CREATED by ACommand:
oAC = ACommand.new print oAC.nCommandNumber NoMethodError: undefined method `nCommandNumber' for #<ACommand:0x345e180> from (irb):15
so how can an object created by ACommand find the value of this attribute?
oAC.class.nCommandNumber => 123
one of the attributes of the object is the class that created it.
How would this be done in a lesser object orientated language? Probably using techniques such as:
1 class Command 2 def GetCommandNumber 3 raise RuntimeError, "Pure base function called" 4 end 5 end 6 7 class ACommand < Command 8 def GetCommandNumber 9 return 123 10 end 11 end
or
1 class Command 2 def initialize( nCommandNumber) 3 @nCommandNumber = nCommandNumber 4 end 5 end 6 7 class ACommand < Command 8 def initialize 9 super( 123) 10 end 11 end
or something similar. Like all syntactic sugar, it doesn't make the impossible possible (anything is possible in hand-coded assembler) it just makes for less typing and clearer code.


This is the most straightforward explanation of Ruby Metaclasses I have seen, well done, and thank you. I had pretty much gathered this already after bashing my head against a wall while reading half a dozen other explanations...keep up the good work.