Ruby:访问对象时alias_方法的意外行为

Ruby:访问对象时alias_方法的意外行为,ruby,Ruby,在Ruby中,可以通过多种方式重新定义方法。一个是打开本征类或单例类,另一个是使用instance\u eval。但是,alias_方法仅在本征类上可用。为什么会这样,或者有没有一种方法可以将它与instance\u eval一起使用 class << ENV # works alias_method :original_brackets, :[] # works def [](name) # ... end end ENV.instance_eval

在Ruby中,可以通过多种方式重新定义方法。一个是打开本征类或单例类,另一个是使用
instance\u eval
。但是,
alias_方法
仅在本征类上可用。为什么会这样,或者有没有一种方法可以将它与
instance\u 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
类是
模块
类的一部分。在
instance\u eval
的块中,
self
ENV
对象,不能访问
模块
方法

ENV.instance_eval do
  p self.class
end
#=> Object

通常,您可以使用以下技术在
instance\u 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\u方法
是私有方法,在类/模块定义之外不可访问


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

以下是如何做到这一点:

ENV.instance_eval do

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

  def [](name)
  end

end
或者:

ENV.instance_eval do
  class << self
    alias_method :original_brackets, :[] 
  end

  def [](name)
  end
end
ENV.instance\u eval do

课堂很有趣。这是有道理的。那么我如何在ENV上找到该方法呢?我尝试了ENV.singleton_方法和ENV.singleton_class.methods,但都没有返回:alias_method.Try ENV.class.instance_methods称为singleton class
ENV.class.methods.sort==ENV.singleton_class.methods.sort#=>true