理解Ruby mixin的代理类机制

时间:2015-04-14 19:27:39

标签: ruby module scope mixins proxy-classes

我正在参考以下文章,paragaph“陷阱#1”:http://definingterms.com/2013/03/23/pitfalls-of-ruby-mixins/

我有以下设置,稍微改变了文章中使用的形式:

module EmailReporter
    def send_report
        #Sending a report ...
        puts self.class
    end
end

class Person
end

class Employee < Person
    include EmailReporter
end

据我所知,当我在Employee中包含EmailReporter时,其方法不仅仅粘贴到其中,而是创建一个匿名代理类并将其放入Employee上方和Person下的继承链中。

当我调用Employee.new.send_report时,我不在Employee的范围内,而是在代理类的范围内。因此,我无法访问Employee的常量或类变量,但我可以访问实例变量。

问题:

  1. 如果我运行Employee.new.send_report,则输出为“Employee”,但不是“Employee__proxy_class”。这是为什么?不应该“自我”指代理类吗?

  2. 本文建议代理类委托对Module EmailReport的方法调用。但是你当然不能只调用实例方法。那么代理类将其调用委托给谁?

  3. 感谢大家试图回答我的问题!

1 个答案:

答案 0 :(得分:1)

我认为你的根本问题在于理解self的价值。通常,只需添加代码即可告诉您self在代码的不同位置有什么用处。让我们从一个非常简单的例子开始:

class Dad
  def hi
    puts "self in Dad#hi = #{self}"
  end
end

class Son < Dad
end

son = Son.new
  #=> #<Son:0x007fc1f2966b88>
son.methods.include?(:hi)
  #=> true
son.hi
  # self in Dad#hi = #<Son:0x007fc1f2966b88>

仅仅因为:

son.method(:hi).owner
  #=> Dad
self上调用hi时,

并不意味着self已更改。现在让我们来包含一个mixin:

module Helper
  def hi
    puts "self in Helper#hi = #{self}"
  end
end

Son.include Helper

son.hi
  # self in Helper#hi = #<Son:0x007fc1f29551d0>
son.method(:hi).owner
  #=> Helper 

我想您理解为什么在此处调用Helper#hi而不是Dad#hi

这是否回答了您的第一个问题?我不明白第二个问题,但也许你可以自己回答,因为你已经在self开悟了。如果没有,请澄清#2(编辑你的问题)。