Ruby:访问对象时alias_method的意外行为

时间:2016-02-03 15:59:40

标签: ruby

在Ruby中,您可以通过多种方式重新定义方法。一种是打开本征类或单例类,另一种是使用instance_eval。但是,alias_method仅适用于本征类。为什么会这样,或者有没有办法在instance_eval中使用它?

class << ENV
  # works
  alias_method :original_brackets, :[]

  # works
  def [](name)
    # ...
  end
end

ENV.instance_eval do
  # raises NoMethodError
  alias_method :original_brackets, :[]

  # works
  def [](name)
    # ...
  end
end

1 个答案:

答案 0 :(得分:3)

alias_methodalert(JSON.parse(data).alert); 课程的一部分。在Module区块内,instance_evalself对象,无法访问ENV方法。

Module

通常,您可以使用以下技术在ENV.instance_eval do p self.class end #=> Object 中为方法添加别名:

instance_eval

在上述情况下,class Foo def bar end end p Foo.instance_methods(false) #=> [:bar] Foo.new.instance_eval do self.class.send :alias_method, :bar_orig, :bar end p Foo.instance_methods(false) #=> [:bar, :bar_orig] 必须使用send是私有方法,并且在类/模块定义之外无法访问。

但是,alias_method不是任何特殊目的类的实例(例如ENV) - 相反,它是Foo类的实例,其中添加了许多单例方法。因此,上述技术不起作用,而是必须使用Objectsingleton对象添加别名。

以下是如何做到的:

ENV

或者:

ENV.instance_eval do

  singleton_class.send :alias_method, :original_brackets, :[] rescue p "oops"

  def [](name)
  end

end