The language mostly refers to them as "singleton classes", because logically speaking there is exactly one of them for every object.
Every Ruby object is an instance of its singleton class. Even when it appears to be an instance of, say, "File" or "Hash", their true individual identity is their singleton. Hence with:
Most significantly, this class is where any per-object method is actually contained, hence:
class Foo
def self.hello
42
end
end
Foo.hello #=> 42
Foo.singleton_class.instance_methods(false) #=> [:hello]
There are three things worth observing that, once fully absorbed, helped me understand all this more instinctively:
1. All Ruby methods are the instance methods of a class.
2. What we call class methods, such as Foo.hello above, are technically instance methods of the singleton class of a Class object. But that's something of a mouthful, so we say class method instead.
3. Extending an object with a module is, by definition, including that module in the ancestors of its singleton.
It's dangerous to assume that definition by keyword is syntactic sugar, because there are crucial lexical differences that will bite the novice metaprogrammer on the backside. For example, writing
class Foo; end
differs from
Foo = Class.new
since the former will open an existing class, whilst the latter will overwrite the constant with a new class, and then the cref (roughly speaking, constant search path) is different due to the module nesting structure; hence:
class Foo
MAGIC_NUMBER=42
def self.hello1
MAGIC_NUMBER
end
end
def Foo.hello2
MAGIC_NUMBER
end
Foo.hello1 #=> 42
Foo.hello2 #=> NameError: uninitialized constant MAGIC_NUMBER
and worse:
Bar = Class.new do
MAGIC_NUMBER = 99
end
defines MAGIC_NUMBER as a top-level constant, not as Bar::MAGIC_NUMBER, which is bad enough in itself, but now
Foo.hello2 #=> 99
which is the kind of subtle misbehaviour that drives people nuts trying to resolve.
Without going into the arcane detail, there are similarly subtle variations that'll show up, involving the default definee (aka the third implicit context), and closures contained in the class definitions.
So I'm very sparing in my use of Class.new and even Module.new, I'll restrict them to carefully written framework methods.
> Class method is just a method of objects class
You'd hope. But look at the mechanics of Kernel#class. Objects don't work from a reference to their (apparent) class, the obj->klass pointer doesn't necessarily go there; it references the head of the linked list of all ancestors, and if you've referred to the singleton in any fashion it'll point to that (absent funny business like prepending the singleton). Then rb_class_real has to iterate along the list skipping the singleton and any ICLASS entries, and assumes the first thing it sees otherwise is the class you meant.
The point being that an object's apparent class is defined by the first object in its ancestors list that isn't its singleton class or a included/prepended module. In theory, this should be invariant across the object's lifetime. In practice, Ruby recomputes it each time. The reason for this is that as soon as you reference the singleton of an object, Ruby a) allocates it, and b) updates the obj->klass pointer to be the singleton, not the class it was made from.
Also, you can screw with people's assumptions via def foo.class; Object; end, which just demonstrates how wilfully ignoring the Law of Demeter gets you into trouble.
It’s a class dedicated to a single object. Every object has its own eigenclass — this sounds expensive but in practice they’re lazily created. Regular classes are used to store the definitions of methods which are available on all instances of that class. In contrast, a single object’s eigenclass is used to store the definitions of methods which are available on that object only.
`def foo.bar … end` defines a `bar` method in the eigenclass of the object `foo`, which can then be called with `foo.bar`. (This is how “class methods” work in Ruby: their definitions are stored in the class object’s eigenclass so that those methods can be called only on that specific class rather than all classes.)
It's like a "shadow class" that's unique to an instance of something. No written description of this concept ever really 'clicked' for me, personally, so maybe an example will help. Here's a class with a single method `:hello` that will simultaneously increment a counter on its class and on its singleton_class/eigenclass/metaclass:
irb:1* my_class = Class.new do
irb:2* def hello
irb:2* "I've counted #{self.class.instance_variable_set(:@count, (self.class.instance_variable_get(:@count) || 0) + 1)} of #{self.class}… " +
irb:2* "but only #{self.singleton_class.instance_variable_set(:@count, (self.singleton_class.instance_variable_get(:@count) || 0) + 1)} of #{self.singleton_class}!"
irb:1* end
irb:0> end
irb:0> foo = my_class.new
irb:0> bar = my_class.new
Then if we send :hello a few times to each instance you can see how it behaves:
irb:0> foo.hello
=> "I've counted 1 of #<Class:0x0000561efb9d8238>… but only 1 of #<Class:#<#<Class:0x0000561efb9d8238>:0x0000561efbaa8488>>!"
irb:0> bar.hello
=> "I've counted 2 of #<Class:0x0000561efb9d8238>… but only 1 of #<Class:#<#<Class:0x0000561efb9d8238>:0x0000561efb9d7040>>!"
irb:0> foo.hello
=> "I've counted 3 of #<Class:0x0000561efb9d8238>… but only 2 of #<Class:#<#<Class:0x0000561efb9d8238>:0x0000561efbaa8488>>!"
irb:0> bar.hello
=> "I've counted 4 of #<Class:0x0000561efb9d8238>… but only 2 of #<Class:#<#<Class:0x0000561efb9d8238>:0x0000561efb9d7040>>!"
irb:0> foo.hello
=> "I've counted 5 of #<Class:0x0000561efb9d8238>… but only 3 of #<Class:#<#<Class:0x0000561efb9d8238>:0x0000561efbaa8488>>!"
irb:0> foo.hello
=> "I've counted 6 of #<Class:0x0000561efb9d8238>… but only 4 of #<Class:#<#<Class:0x0000561efb9d8238>:0x0000561efbaa8488>>!"
irb:0> foo.hello
=> "I've counted 7 of #<Class:0x0000561efb9d8238>… but only 5 of #<Class:#<#<Class:0x0000561efb9d8238>:0x0000561efbaa8488>>!"
irb:0> bar.hello
=> "I've counted 8 of #<Class:0x0000561efb9d8238>… but only 3 of #<Class:#<#<Class:0x0000561efb9d8238>:0x0000561efb9d7040>>!"
For a real-world example of how this can be useful, I use this pattern in my Jekyll multimedia toolbox to handle the specifics of any certain type of media file (e.g. images, videos, audio, etc). I defined separate Modules for separate media_type handling, a single instance will detect the media_type of its associated file (from the file extension or filemagic), then the instance will differentiate itself by Module#prepend-ing the media_type-specific Module to the instance's `singleton_class`. Then the next instance for the next possible-different-type media file has a clean undifferentiated base to start from and the process can repeat: https://github.com/okeeblow/DistorteD/blob/master/DistorteD-...