Bac*_*cko 1 ruby methods metaprogramming ruby-on-rails definition
我正在使用Ruby 1.9.2和Ruby on Rails v3.2.2 gem.我正在尝试以"正确的方式"学习元编程,此时我在RoR 模块提供的块中对实例方法进行别名:included do ... endActiveSupport::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
Run Code Online (Sandbox Code Playgroud)
"Newbiely"说,通过在Web上搜索,我想出了singleton_class = class << self; self end语句,并使用它(而不是class << self ... end块)来调整变量的范围my_method_name,使动态生成别名.
我想明白究竟为什么和如何的singleton_class在上面的代码和作品是否有更好的方法(也许,一个更容易维护和高性能的一个)实现相同的(别名,定义单身方法等),而是"正确的方式"因为我认为不是这样.
我推荐Yehuda Katz 关于Ruby自我的metaprogamming的帖子.以下是我对您的问题的回复:
在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
Run Code Online (Sandbox Code Playgroud)
您的Rails版本实际上提供singleton_class了一个快捷方式.由于singleton_class是可用方法,因此您无需将其分配给表达式中的变量singleton_class = class << self; self end:
Person.singleton_class
person = Person.new
person.singleton_class
Run Code Online (Sandbox Code Playgroud)
由于类直接从其singleton类继承,因此我们希望在元编程时动态添加类方法.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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3646 次 |
| 最近记录: |