The Ruby Metaclass
The ruby metaclass (also known as the Singleton class) is a very commonly misunderstood ruby language construct.
Lets look at a simple class definition:
class Dog
def bark
puts "woof woof!"
end
endThe class Dog contains the instance method bark. This is pretty self-explanatory.
What happens when you define a class with class methods (also known as static methods).
In ruby, everything is an object. That means classes are objects too.
class Dog
def self.bark
puts "woof woof!"
end
endThe Dog class above is actually an instance of Class.
> Dog.__id__ => 2152689112 > Dog.class => Class >
If the Dog class contains instance methods, what class contains the Dog’s class methods?
You might at first think Class class contains the Dog class methods. If is true, all instances of Class should contain bark method right? That wouldn’t really make sense if it behaved like that would it?
Introducing the Metaclass (also known as the Singleton class)
In between Class and Dog is a class called the Metaclass. An object’s metaclass is a Singleton class that objects inherits it’s methods from. The reason why it is so confusing is primarily due to the fact that they are invisible. You can, however, get a hold of the metaclass:
> metaclass = class << Dog; self; end => #<Class:Dog> > metaclass.instance_methods => [:bark, :allocate, :new, :superclass, :freeze, :===, :==, :<=>, :<, :<=, :>, :>=, :to_s, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods, :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?, :const_missing, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set, :class_variable_defined?, :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?, :public_method_defined?, :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload, :autoload?, :instance_method, :public_instance_method, :nil?, :=~, :!~, :eql?, :class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :hash, :__id__, :object_id, :to_enum, :enum_for, :gem, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__]
Lets add a couple more methods to the Dog class using the metaclass:
metaclass.class_eval do
def sit
puts "<sits down>"
end
end
Dog.sit => "<sits down>"You may have came across code that used the following idiom to define class methods.
class Dog
class << self
def sit
puts "<sits down>"
end
end
endWhat we are actually doing above is defining a sit instance method in Dog’s metaclass.