in Ruby you can reopen existing classes and add methods. That is, you can say:
class Foo
def bob
return "hello from bob"
end
end
these methods get stored somewhere in an internal dictionary (maybe an instance variable) of the Foo
-class (which is just an instance of the Class
-class and therefore has instance variables)
But the suprising thing is, that you can also add methods to instances of existing objects
foo = Foo.new
foo2 = Foo.new
def foo.fred
return "I am fred"
end
foo.fred #=> "I am fred"
foo2.fred #=> NoMethodError
but Where is this method actually stored?
Turns out Ruby creates a new class behind the scenes (sometimes called singleton class, metaclass or eigenclass) which gets inserted in the inheritance heirarchy between the Foo
-class and its instance.
So the inheritance relationship looks like that:
foo < (eigenclass of foo) < Foo < Class
(if you say foo.superclass you will not see the singleton class)
the class << X
-syntax is a way to get to this special class, so that you can manipulate it directly. The following code blocks are exactly equivalent:
def foo.bar
return "xy"
end
# is exactly the same as
class << foo
def bar
return "xy"
end
end
So the similarity between class Foo < Bar
and class << Foo
is not accidental, there is inheritance going on in both.
Think of class << X
as "open up the metaclass of X"
The thing to remember in Ruby is that classes themselves are just objects. (Instances of the class Class
) so if you say:
class Foo
class << self
def k
return "x"
end
end
end
(self
is bound to Foo
in this code block) so k
is an instance method of the eigenclass of Foo
, which makes it a class method for Foo
all this is explained more clearly in the chapter about classes of the Pickaxe (the web version does not contain the diagrams, unfortunately) and _whys Seeing Metaclasses Clearly