An anonymous class!
bear = Class.new
puts bear
# => #<Class:0x8ef08>
puts bear.class
# => Class
puts bear.name
# => ""
This class has no name, it's anonymous. Let's create an instance of the anonymous class.
b = bear.new
puts b.class
#=> #<Class:0x8ef08>
Normally, b.class
would return the class name. Anonymous means no name. Ruby returns an instance of class (the one created with Class.new
) insntead.
A class name is always a constant. The call class Foo; end
tells Ruby to create an instance of Class
and assign that instance to the constant Foo
. These two calls are equal:
class Foo; end
Foo = Class.new
Let's try this with our anonymous class. We're assigning the instance of Class
stored in the variable bear
to a constant, Bear
.
Bear = bear
puts b.class
# => Bear
puts b.name
# => "Bear"
It now reports Bear
as the class name, because it's no longer anonymous.
Our instance of Class
seems to have vanished, but it's still possible to access this instance directly.
class << Bear
puts self
# => #<Class:Bear>
end
It couldn't hide from us after all. The special (class <<
) syntax lets us access it. It also says Bear
rather than 0x8ef08
, to let us know that this class is no longer anonymous.
This secret and hidden instance of Class
is what rubyists refers to as the _metaclass_ of a class. #<Class:Bear>
is the metaclass of Bear
.
It's this metaclass that holds all the class methods. That makes sense, because a constant can't have methods. Instances is the only thing in Ruby that has methods.
Important summary: Class methods of a class are simply instance methods of its metaclass. Read this out loud 10 times.
Code speaks louder than words
Bear.class_eval do
def say_hello
puts "Hello!"
end
end
Bear.say_hello
# => NoMethodError: undefined method ‘say_hello’ for Bear:Class
We need to define the method on the metaclass, the instance of Class
.
class << Bear
def say_hello
puts "Hello!"
end
end
Bear.say_hello
# => "Hello!"
Further reading
_why the lucky stiff has more on the subject.