在别名实例方法时理解单例类

时间:2012-10-17 14:56:31

标签: ruby-on-rails ruby methods metaprogramming definition

我正在使用Ruby 1.9.2和Ruby on Rails v3.2.2 gem。我正在尝试以“正确的方式”学习元编程,此时我在RoR ActiveSupport::Concern模块提供的included do ... end块中对实例方法进行别名处理:

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

“Newbiely”说,通过在网上搜索,我想出了singleton_class = class << self; self end语句,我用它(而不是class << self ... end块)来范围 my_method_name变量,动态生成别名。

我想完全理解为什么 singleton_class如何在上面的代码中工作,如果有更好的方法(也许,更易于维护)和performant one)实现相同(别名,定义单例方法等),但“正确的方法”因为我认为不是这样。

1 个答案:

答案 0 :(得分:6)

我推荐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_evalinstance_eval。这些行为的方式存在细微差别(Yehuda的帖子解释了这一点),但是你可以使用任何一个来输入你的单例类的范围,将单例类的方法解析为self并且仍然可以访问{{1来自周围的范围。

所有这一切,您可以对您的模块进行一些小的更改:

my_method_name
相关问题