class << self idiom in Ruby
class << self在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"'
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.
I found a super simple explanation about class << self , Eigenclass and different type of methods in this blog.
In Ruby, there are three types of methods that can be applied to a class:
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
end
foo = Foo.new
def 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.new
class << foo
def a_singleton_method
puts "I am a singleton method"
end
end
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
end
end
What class << thing does:
class Hi
self #=> Hi
class << self #same as 'class << Hi'
self #=> #<Class:Hi>
self == Hi.singleton_class #=> true
end
end
[it makes self == thing.singleton_class in the context of its block] .
What is thing.singleton_class?
hi = String.new
def hi.a
end
hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true
hi object inherits its #methods from its #singleton_class.instance_methods and then from its #class.instance_methods .
Here we gave hi 's singleton class instance method :a . It could have been done with class << hi instead.
hi 's #singleton_class has all instance methods hi 's #class has, and possibly some more ( :a here).
[instance methods of thing's #class and #singleton_class can be applied directly to thing. when ruby sees thing.a, it first looks for :a method definition in thing.singleton_class.instance_methods and then in thing.class.instance_methods]
By the way - they call object's singleton class == metaclass == eigenclass .
链接地址: http://www.djcxy.com/p/4360.html上一篇: 如何在Ruby中写入文件?
下一篇: Ruby中的自我成语
