ruby - Ruby 中的 method_missing 陷阱

标签 ruby metaprogramming

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

最佳答案

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

稍后:

一个例子:

# 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 - Ruby 中的 method_missing 陷阱,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/291132/

相关文章:

ruby - Ruby 是否有 nil 值的安全导航运算符的语法,就像在 Groovy 中一样?

ruby-on-rails - 获取每个用户的文件夹大小和所有内容

ruby - 我怎样才能将这段代码转换为元编程,这样我就可以停止复制它了?

c++ - Boost.Fusion 运行时开关

C++ 如何将 "overload"模板用于值和类型?

ruby - 计算 Ruby 中的大写字母

ruby - 如何立即打印标准输出?

ruby - 如何创建自定义 while block

c++ - 可以在没有 typedef 的情况下访问模板外部的模板参数吗?

ruby - 如何检索类名?