|
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: class Foo; end
foo = Foo.new
then foo.singleton_class #=> #<Class:#<Foo:0x00007ff6cc195ee0>>
foo.singleton_class < Foo #=> true
foo.is_a?(foo.singleton_class) #=> true
foo.singleton_class.ancestors #=> [#<Class:#<Foo:0x00007ff6cc195ee0>>, Foo, Object, Kernel, BasicObject]
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. |