新手问题 prepended 里使用 class_eval 时遇到了奇怪的问题

mizuhashi · 2015年12月16日 · 最后由 mizuhashi 回复于 2015年12月16日 · 1696 次阅读
module M
  def self.prepended(clz)
    clz.class_eval do
      def [](k)
        p 1
      end
    end
  end
end

module N
  def self.included(clz)
    clz.class_eval do 
      def []=(k, v)
        p 2
      end
    end
  end
end

class Hash
  prepend M
  include N
end

Hash.new[1]
Hash.new[1]=1

这段代码执行的时候什么也没有输出,按我的理解,应该会输出 1 2。 但是我的 prepend 模块并没有方法,只是利用了一下钩子,为什么 eval 里覆写的方法会失效?而且 prepend 导致 include 的覆写也失效了。 如果注释掉 prepend M,[]=的覆写是可以生效的,整段用 included 写的话是完全可行的。 我觉得这里和方法查找链不应有联系,但是我也想不到 prepend 和 include 的其他区别了。

module M
end

class Hash
  prepend M
end

class Hash
  def [](k)
    p 3
  end

  def map
    p 4
  end
end

h = {a: 1}
h[:a] #=> return 1 and without print 3
h.send(:[], :a) #=> print 3
h.map #=> print 4

简化成了这样,基本确定和[key]的调用有关系,怀疑是 [] 方法有些特殊的处理

需要 登录 后方可回复, 如果你还没有账号请 注册新账号