method_missing
在Ruby中定义方法时有什么需要注意的吗?我想知道是否存在一些不那么明显的继承,异常抛出,性能或其他任何东西的交互.
一个显而易见的问题: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
如果你的方法缺失方法只是寻找某些方法名称,如果你没有找到你正在寻找的东西,不要忘记调用super,以便其他方法缺失可以做他们的事情.
如果可以预测方法名称,最好动态声明它们而不是依赖method_missing,因为method_missing会导致性能损失.例如,假设您希望扩展数据库句柄,以便能够使用以下语法访问数据库视图:
selected_view_rows = @dbh.viewname( :column => value, ... )
您可以提前确定数据库中的所有视图,然后迭代它们以在@dbh上创建"viewname"方法,而不是依赖于数据库句柄上的method_missing并将方法名称作为视图名称分派给数据库. .
基于Pistos的观点:method_missing
至少比常规方法调用我尝试过的所有Ruby实现要慢一个数量级.他有可能在可能的情况下避免打电话method_missing
.
如果您喜欢冒险,请查看Ruby鲜为人知的Delegator课程.