动态定义方法

使用 Ruby,你可以在执行时修改程序的结构。一种方法是使用方法 method_missing 动态定义方法。

假设我们希望能够使用语法 777.is_greater_than_123? 测试数字是否大于其他数字。

# open Numeric class
class Numeric
  # override `method_missing`
  def method_missing(method_name,*args)
    # test if the method_name matches the syntax we want
    if method_name.to_s.match /^is_greater_than_(\d+)\?$/
      # capture the number in the method_name
      the_other_number = $1.to_i
      # return whether the number is greater than the other number or not
      self > the_other_number
    else
      # if the method_name doesn't match what we want, let the previous definition of `method_missing` handle it
      super
    end
  end
end

使用 method_missing 时要记住的一件重要事情是,还应该覆盖 respond_to? 方法:

class Numeric
   def respond_to?(method_name, include_all = false) 
     method_name.to_s.match(/^is_greater_than_(\d+)\?$/) || super
   end
end

忘记这样做会导致一个不一致的情况,当你可以成功调用 600.is_greater_than_123,但 600.respond_to(:is_greater_than_123) 返回 false。