Ruby:Monkey修补String类

dav*_*k01 3 ruby monkeypatching metaprogramming

我有点困惑为什么以下代码实际工作:

String.instance_eval do # self is set to String
  [:readlink, :symlink?, :expand_path].each do |method| # self is still String
    define_method(method) do # self is still String
      File.send(method, self) # what exactly is this self?
    end
  end
end
"asdf".expand_path # => "C:/users/some_user/asdf"
Run Code Online (Sandbox Code Playgroud)

我不明白为什么最后一行有效.当每个方法定义的方法体不等同于File.send(method, String)?上述块中没有一个实际发生变化self.唯一更改的行selfString.instance_eval,它会更改selfString.

Ser*_*sev 5

File.send(method, self)
Run Code Online (Sandbox Code Playgroud)

self将在将调用动态生成的方法时进行评估.此时它将被设置为String的实例.(在你的例子中是"asdf").

它实际上相当于打开String类并手动编写所有这些方法.

class String
  def readlink
    File.send :readlink, self
  end

  def expand_path
    File.send :expand_path, self
  end
end
Run Code Online (Sandbox Code Playgroud)