class << self idiom in Ruby
First, the class << foo
syntax opens up foo
's singleton class (eigenclass). This allows you to specialise the behaviour of methods called on that specific object.
a = 'foo'class << a def inspect '"bar"' endenda.inspect # => "bar"a = 'foo' # new object, new singleton classa.inspect # => "foo"
Now, to answer the question: class << self
opens up self
's singleton class, so that methods can be redefined for the current self
object (which inside a class or module body is the class or module itself). Usually, this is used to define class/module ("static") methods:
class String class << self def value_of obj obj.to_s end endendString.value_of 42 # => "42"
This can also be written as a shorthand:
class String def self.value_of obj obj.to_s endend
Or even shorter:
def String.value_of obj obj.to_send
When inside a function definition, self
refers to the object the function is being called with. In this case, class << self
opens the singleton class for that object; one use of that is to implement a poor man's state machine:
class StateMachineExample def process obj process_hook obj endprivate def process_state_1 obj # ... class << self alias process_hook process_state_2 end end def process_state_2 obj # ... class << self alias process_hook process_state_1 end end # Set up initial state alias process_hook process_state_1end
So, in the example above, each instance of StateMachineExample
has process_hook
aliased to process_state_1
, but note how in the latter, it can redefine process_hook
(for self
only, not affecting other StateMachineExample
instances) to process_state_2
. So, each time a caller calls the process
method (which calls the redefinable process_hook
), the behaviour changes depending on what state it's in.
I found a super simple explanation about class << self
, Eigenclass
and different type of methods.
In Ruby, there are three types of methods that can be applied to a class:
- Instance methods
- Singleton methods
- Class methods
Instance methods and class methods are almost similar to their homonymous in other programming languages.
class Foo def an_instance_method puts "I am an instance method" end def self.a_class_method puts "I am a class method" end endfoo = Foo.newdef foo.a_singleton_method puts "I am a singletone method"end
Another way of accessing an Eigenclass
(which includes singleton methods) is with the following syntax (class <<
):
foo = Foo.newclass << foo def a_singleton_method puts "I am a singleton method" endend
now you can define a singleton method for self
which is the class Foo
itself in this context:
class Foo class << self def a_singleton_and_class_method puts "I am a singleton method for self and a class method for Foo" end endend
Usually, instance methods are global methods. That means they are available in all instances of the class on which they were defined. In contrast, a singleton method is implemented on a single object.
Ruby stores methods in classes and all methods must be associated with a class. The object on which a singleton method is defined is not a class (it is an instance of a class). If only classes can store methods, how can an object store a singleton method? When a singleton method is created, Ruby automatically creates an anonymous class to store that method. These anonymous classes are called metaclasses, also known as singleton classes or eigenclasses. The singleton method is associated with the metaclass which, in turn, is associated with the object on which the singleton method was defined.
If multiple singleton methods are defined within a single object, they are all stored in the same metaclass.
class Zenendz1 = Zen.newz2 = Zen.newclass << z1 def say_hello puts "Hello!" endendz1.say_hello # Output: Hello!z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
In the above example, class << z1
changes the current self to point to the metaclass of the z1 object; then, it defines the say_hello method within the metaclass.
Classes are also objects (instances of the built-in class called Class). Class methods are nothing more than singleton methods associated with a class object.
class Zabuton class << self def stuff puts "Stuffing zabuton…" end endend
All objects may have metaclasses. That means classes can also have metaclasses. In the above example, class << self modifies self so it points to the metaclass of the Zabuton class. When a method is defined without an explicit receiver (the class/object on which the method will be defined), it is implicitly defined within the current scope, that is, the current value of self. Hence, the stuff method is defined within the metaclass of the Zabuton class. The above example is just another way to define a class method. IMHO, it's better to use the def self.my_new_clas_method syntax to define class methods, as it makes the code easier to understand. The above example was included so we understand what's happening when we come across the class << self syntax.
Additional info can be found at this post about Ruby Classes.