我正在使用 Ruby 1.9.2 和 Ruby on Rails v3.2.2 gem。我正在尝试以“正确的方式”学习元编程,此时我在 included do ... end
中为一个实例 方法添加了别名RoR 提供的区 block ActiveSupport::Concern
模块:
module MyModule
extend ActiveSupport::Concern
included do
# Builds the instance method name.
my_method_name = build_method_name.to_sym # => :my_method
# Defines the :my_method instance method in the including class of MyModule.
define_singleton_method(my_method_name) do |*args|
# ...
end
# Aliases the :my_method instance method in the including class of MyModule.
singleton_class = class << self; self end
singleton_class.send(:alias_method, :my_new_method, my_method_name)
end
end
“新手”来说,通过网络搜索,我找到了 singleton_class = class << self; self end
语句,我使用它(而不是 class << self ... end
block )来作用域 my_method_name
变量,使别名动态生成。
我想确切地了解为什么 和如何 singleton_class
在上面的代码中工作,如果有更好的方法(也许是一种更易于维护和更高效的方法)来实现相同的方法(别名,定义单例方法等),但是“正确的方法”,因为我认为它不是'是这样。
最佳答案
我推荐 Yehuda Katz 的 post on metaprogamming on Ruby's self .以下是我对您问题的简单总结:
在 Ruby 中,所有对象都有一个单例类(也称为元类)。对象首先从它们的单例类中无形地继承,然后从它们的显式类中继承。 Ruby 类本身有自己的单例类,因为类也是对象。 class <<
习语只是 Ruby 用于访问对象的单例类范围的语法。
class Person
class << self
# self in this scope is Person's singleton class
end
end
person = Person.new
person_singleton_class = class << person; self; end
您的 Rails 版本实际上提供了 singleton_class
作为捷径。自 singleton_class
是一种可用的方法,您不需要将其分配给表达式 singleton_class = class << self; self end
中的变量:
Person.singleton_class
person = Person.new
person.singleton_class
由于一个类直接继承自它的单例类,这就是我们在元编程时要动态添加类方法的地方。 Ruby 提供了几种方法来打开对象的范围,同时保持对周围范围的访问:class_eval
和 instance_eval
.它们的行为方式存在细微差别(Yehuda 的帖子对此进行了解释),但您可以使用其中一种方法进入单例类的范围,将单例类上的方法解析为 self
。并且仍然可以访问 my_method_name
从周边范围。
总而言之,您可以对模块进行一些小改动:
module MyModule
extend ActiveSupport::Concern
included do
# Builds the instance method name.
my_method_name = build_method_name.to_sym # => :my_method
# Defines the :my_method instance method in the including class of MyModule.
define_singleton_method(my_method_name) do |*args|
# ...
end
singleton_class.class_eval do
# method resolution in scope of singleton class
alias_method :my_new_method, my_method_name
end
end
end
关于ruby-on-rails - 为实例方法起别名时理解单例类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12937209/