Jeffrey Moss wrote:
Being somewhat new to the concept of metaprogramming, I can tell you what is particularly confusing is the use of class << self, how this is like the root of all singleton behavior, how it differs from class a < b (perhaps even display how it works inside the interpreter). I wasn't sure what the difference between the < and the << operator was, so I had to go look it up.
My article briefly discusses the singleton class notation (the << you are referring to). This notation is very simple to understand once you've gotten the hang of:
1. Objects are containers for instance variables.
2. Classes are containers for methods and instance variables.
There are more to objects and classes than this, but for the sake of this discussion, it's useful to whittle it down to this.
a = Object.new
a.instance_variable_set( "@name", "Jeff" )
I've created a new object above, storage for instance variables. I've added an instance variable to the object. In doing so, I called the `instance_variable_set' method. This method isn't contained in the `a' object. It's contained way up the inheritance tree, in the Object class.
Again: the instance variables are stored in the object. The methods are stored in a class up the inheritance tree.
class << a
def name; @name; end
end
We're opening a metaclass here. What is a metaclass? It's method storage for an object. An object can only store instance variables. The `name' method has been added to the metaclass (the personal method storage) for the object `a'.
The most needlessly confusing construct in Ruby is `class << self'. You're simply accessing the method storage for whatever object is currently `self'.
class Dragon
class << self; p self; end
end
Prints: #<Class:Dragon>
Okay, so we're in the metaclass for a class. But what is that?
It's method storage for class methods. Normal instance methods are stored directly in the class. But class methods are stored in the metaclass.
class Dragon
def self.me; p self; end # This method is stored in the metaclass
def me; p self; end # This method is stored in the class
end
Dragon.me #=> Dragon
Dragon.new.me #=> #<Dragon:0x80914e0>
Everyone who uses class methods uses metaclasses.
class << Dragon
def roar; "#<CLASS:ROAR>"; end
end
Dragon.roar #=> #<CLASS:ROAR>
d = Dragon.new
class << d
def roar; "#<OBJ:ROAR>"; end
end
d.roar #=> #<OBJ:ROAR>
I don't really get into this in the article, since I've opted to use the `metaclass' method and `meta_eval' which are alternate forms of the above.
The < operator is a completely different operator, used strictly for setting the superclass of a class.
But one handy thing about metaclass (which I believe qualifies them for the meta- prefix) is that they follow the inheritance tree, simply remaining one level removed.
>> Dragon.metaclass
=> #<Class:Dragon>
>> Dragon.metaclass.superclass
=> #<Class:Object>
>> Dragon.superclass.metaclass
=> #<Class:Object>
See, an object's metaclass' superclass is the same as the object's superclass' metaclass.
Also the difference between class instance variables and class variables could use some extra explaining, it seems you're just saying what to do and what not to do, but not why you can't or shouldn't do it, and why a @@ class variable is handy.
I'll address this once I'm sure I completely understand variable.c and have played around with class variables in metaclasses a bit more.
_why