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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…