通过"良好的基础Rubyist"书。在第4章中,它介绍了如何覆盖method_missing
方法的示例。它解释得很清楚的原因是你想要首先做到这一点?覆盖method_missing
方法的目的是什么?
答案 0 :(得分:2)
这是元编程所必需的,如果事先不知道,那个对象“预期”的方法。
Naïve示例(为所有派生类的所有实例变量实现attr_reader
:
class A
def method_missing m, *args, &cb
return instance_variable_get(:"@#{m}") if instance_variables.include? :"@#{m}"
super
end
end
class B < A
def initialize
@b = 42
end
end
B.new.b
#⇒ 42
对于更复杂的示例,可以查看Rails代码,其中包含method_missing
个。
答案 1 :(得分:2)
我不确定您正在阅读的Well Grounded Rubyist
版本(考虑切换到第二版),但后者实际上会让您了解method_missing
可以使用的内容对于。第113页的清单4.13 为您提供了一组结合一些类似的方法的想法,例如
class Person
def all_with_children
# some select...
end
def all_with_parents
# seems like another select but joined with another table...
end
def all_with_cars
# the same here...
end
def all_with_house
# woah, four methods doing slightly the same!
end
# so what if you have 100 database attributes and want to
# provide a selector for all of them?
end
使用method_missing
代替一些元编程:
def self.method_missing m, *args
method = m.to_s
if method.start_with? ("all_with_")
# now we know that we're going to do SELECT.
# the only thing to consider is what table should be joined.
# we defer that from the right part of the method name
# e.g. "children" for "all_with_children"
# in case we gonna ask for "all_with_wife" we won't need to add new method!
end
在Ruby on Rails 4
之前,调用类似Person.find_by_username
的内容是一种常见的模式,它隐含了相同的method_missing
逻辑。
将method_missing
视为一种方法,使您有机会在应用程序因未知方法调用而失败之前执行某些操作。
您可能希望在失败时添加一些调试信息(将扩展错误描述记录到日志文件中,或向管理员发送电子邮件,说明出现了问题)。
method_missing
可以让您只需几行就可以为所有属性定义自己的getter / setters方法。
简而言之,它为您提供了另一个编写简短且可读代码的机会。请注意,它不应该被滥用,因为您需要为其使用付出一些代价(包括整体代码复杂性和执行时间)。
答案 2 :(得分:1)
想象一下,如果您想要在不事先定义方法的情况下动态响应方法,或者因为一组方法名称使用相似/相同的代码来列出可能性。
例如,您可以使用具有固定价格的不同类,但您希望轻松为大量货币添加转化。所以你可以这样做:obj.price_euro,obj.price_usd等等。所有这些都可以被method_missing捕获。
这并不是一个好主意或坏主意。
请注意,如果您覆盖method_missing,那么您将比定义&#34; def方法慢得多,并且不要忘记更新respond_to?匹配!