Rea*_*nly 49 ruby metaprogramming
method_missing在Ruby中定义方法时有什么需要注意的吗?我想知道是否存在一些不那么明显的继承,异常抛出,性能或其他任何东西的交互.
Jam*_*sen 60
一个显而易见的问题: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
Run Code Online (Sandbox Code Playgroud)
Pis*_*tos 11
如果可以预测方法名称,最好动态声明它们而不是依赖method_missing,因为method_missing会导致性能损失.例如,假设您希望扩展数据库句柄,以便能够使用以下语法访问数据库视图:
selected_view_rows = @dbh.viewname( :column => value, ... )
Run Code Online (Sandbox Code Playgroud)
您可以提前确定数据库中的所有视图,然后迭代它们以在@dbh上创建"viewname"方法,而不是依赖于数据库句柄上的method_missing并将方法名称作为视图名称分派给数据库. .