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"'
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 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.
Best Answer
First, the
class << foo
syntax opens upfoo
's singleton class (eigenclass). This allows you to specialise the behaviour of methods called on that specific object.Now, to answer the question:
class << self
opens upself
's singleton class, so that methods can be redefined for the currentself
object (which inside a class or module body is the class or module itself). Usually, this is used to define class/module ("static") methods:This can also be written as a shorthand:
Or even shorter:
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:So, in the example above, each instance of
StateMachineExample
hasprocess_hook
aliased toprocess_state_1
, but note how in the latter, it can redefineprocess_hook
(forself
only, not affecting otherStateMachineExample
instances) toprocess_state_2
. So, each time a caller calls theprocess
method (which calls the redefinableprocess_hook
), the behaviour changes depending on what state it's in.