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"' end end a.inspect # => "bar" a="foo" # new object, new singleton class a.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 end end String.value_of 42 # => "42"
This can also be written as a shorthand:
class String def self.value_of obj obj.to_s end end
Or even shorter:
def String.value_of obj obj.to_s end
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 end private 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_1 end
So, in the example above, each instance of
process_hook aliased to
process_state_1, but note how in the latter, it can redefine
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.