当前位置:  开发笔记 > 后端 > 正文

在Ruby中使用method_missing陷阱

如何解决《在Ruby中使用method_missing陷阱》经验,为你挑选了4个好方法。

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



1> James A. Ros..:

一个显而易见的问题: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 1.9.2中,重新定义`respond_to_missing更好吗?`,请参阅我的博客文章:http://blog.marc-andre.ca/2010/11/methodmissing-politely.html
这里应该做一些修正:1)`respond_to?`实际上有两个参数.未能指定第二个参数可能会导致细微的参数错误(请参阅http://technicalpickles.com/posts/using-method_missing-and-respond_to-to-create-dynamic-methods/)2)您无需将参数传递给在这种情况下超级.`super`使用原始参数隐式调用超类方法

2> Andrew Grimm..:

如果你的方法缺失方法只是寻找某些方法名称,如果你没有找到你正在寻找的东西,不要忘记调用super,以便其他方法缺失可以做他们的事情.



3> Pistos..:

如果可以预测方法名称,最好动态声明它们而不是依赖method_missing,因为method_missing会导致性能损失.例如,假设您希望扩展数据库句柄,以便能够使用以下语法访问数据库视图:

selected_view_rows = @dbh.viewname( :column => value, ... )

您可以提前确定数据库中的所有视图,然后迭代它们以在@dbh上创建"viewname"方法,而不是依赖于数据库句柄上的method_missing并将方法名称作为视图名称分派给数据库. .



4> James A. Ros..:

基于Pistos的观点:method_missing至少比常规方法调用我尝试过的所有Ruby实现要慢一个数量级.他有可能在可能的情况下避免打电话method_missing.

如果您喜欢冒险,请查看Ruby鲜为人知的Delegator课程.

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有