在Ruby中定义method_missing方法时,有什么需要注意的吗?我想知道是否有一些不太明显的交互来自继承、异常抛出、性能或其他方面.

推荐答案

有一点很明显:如果你重新定义了method_missing,那么一定要重新定义respond_to?.如果method_missing(:sym)有效,respond_to?(:sym)应该总是返回true.许多图书馆都依赖于此.

Later:

例如:

# Wrap a Foo; don't expose the internal guts.
# Pass any method that starts with 'a' on to the
# Foo.
class FooWrapper
  def initialize(foo)
    @foo = foo
  end
  def some_method_that_doesnt_start_with_a
    'bar'
  end
  def a_method_that_does_start_with_a
    'baz'
  end
  def respond_to?(sym, include_private = false)
    pass_sym_to_foo?(sym) || super(sym, include_private)
  end
  def method_missing(sym, *args, &block)
    return foo.call(sym, *args, &block) if pass_sym_to_foo?(sym)
    super(sym, *args, &block)
  end
  private
  def pass_sym_to_foo?(sym)
    sym.to_s =~ /^a/ && @foo.respond_to?(sym)
  end
end

class Foo
  def argh
    'argh'
  end
  def blech
    'blech'
  end
end

w = FooWrapper.new(Foo.new)

w.respond_to?(:some_method_that_doesnt_start_with_a)
# => true
w.some_method_that_doesnt_start_with_a
# => 'bar'

w.respond_to?(:a_method_that_does_start_with_a)
# => true
w.a_method_that_does_start_with_a
# => 'baz'

w.respond_to?(:argh)
# => true
w.argh
# => 'argh'

w.respond_to?(:blech)
# => false
w.blech
# NoMethodError

w.respond_to?(:glem!)
# => false
w.glem!
# NoMethodError

w.respond_to?(:apples?)
w.apples?
# NoMethodError

Ruby相关问答推荐

Rbenv说未安装已安装的版本

碰撞检测测试中对象的 Nil 类

确保 Capybara 不存在元素

如何在 Ruby 中合并多个哈希?

什么是 Sinatra/Rack 的非常简单的身份验证方案

为 Ruby 模块中的每个方法调用执行代码

C# ?? Ruby 中的运算符?

卸载所有 gem Ruby 2.0.0

class_eval、class_exec、module_eval 和 module_exec 有什么区别?

如何删除Ruby中数组中满足条件的所有元素?

从字符串中删除所有特殊字符 - ruby

如何通过反射获得活动记录关联

判断是否在 SASS 中定义了变量

在 Ruby 中查找内存泄漏的原因

我们什么时候在 Rails 中使用 "||=" 运算符?它的意义是什么?

为什么 __FILE__ 大写而 __dir__ 小写?

等号 ('=') 放在方法定义中的方法名称之后有什么作用?

如何使用器重新安装 gem

如何在 Mac OS Sierra 10.12 上安装 Nokogiri

查找模块中可用的类