class << self
attr_accessor :n, :totalX, :totalY
end
The syntax above is used for defining class instance variables. But when I think about what syntax implies, it doesn't make any sense to me, so I'm wondering if this type of syntax is used for any other types of definitions. My point of confusion here is this:
class << self
The append operator normally means "add what's on the right to the object on the left". But in the context of this block, how does that add up to "put the contents of this block into the definition of the class instance rather than the instance"?
For the same reason I'm confused as to why in one context class << self can define class instance variables while in another it seems to create class variables such as here:
class Point
# Instance methods go here
class << self
# Class methods go here
end
end
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