ruby-on-rails - 为实例方法起别名时理解单例类

标签 ruby-on-rails ruby methods metaprogramming definition

我正在使用 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_evalinstance_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/

相关文章:

Ruby - 欧拉计划 #18 - 最大路径总和

javascript - 创建对具有使用相同范围的参数的方法的引用 - 在 Javascript 中

javascript - 如何从 addEventListener() 调用中调用对象方法?

ruby-on-rails - Intellij IDEA/文件监视程序: bootstrap file to import not found

Ruby 连接最佳实践

html - 单选按钮的样式导致页面上第一个表单之外的表单变得无响应。

ruby-on-rails - rails 3.2 使用的默认 gem

java - 如何创建类和链接方法

ruby-on-rails - Rails - Devise Gem 删除注册和忘记密码模块

ruby-on-rails - 在 Rails 中,如何从现有模型生成显示 View ?