我有几个扩展方法缺失的模块:
module SaysHello
def respond_to?(method)
super.respond_to?(method) || !!(method.to_s =~ /^hello/)
end
def method_missing(method, *args, &block)
if (method.to_s =~ /^hello/)
puts "Hello, #{method}"
else
super.method_missing(method, *args, &block)
end
end
end
module SaysGoodbye
def respond_to?(method)
super.respond_to?(method) || !!(method.to_s =~ /^goodbye/)
end
def method_missing(method, *args, &block)
if (method.to_s =~ /^goodbye/)
puts "Goodbye, #{method}"
else
super.method_missing(method, *args, &block)
end
end
end
class ObjectA
include SaysHello
end
class ObjectB
include SaysGoodbye
end
这些都很好用,例如
ObjectA.new.hello_there
输出"Hello, hello_there"
。同样,ObjectB.new.goodbye_xxx
输出"Goodbye, xxx"
。使用respond_to?
也可以,例如ObjectA.new.respond_to? :hello_there
返回true。然而,当您想同时使用
SaysHello
和SaysGoodbye
时,这种方法就不太适用了。class ObjectC
include SaysHello
include SaysGoodbye
end
ObjectC.new.goodbye_aaa
能正常工作,但ObjectC.new.hello_a
的表现却有些奇怪:
> ObjectC.new.hello_aaa
Hello, hello_aaa
NoMethodError: private method `method_missing' called for nil:NilClass
from test.rb:22:in `method_missing' (line 22 was the super.method_missing line in the SaysGoodbye module)
输出结果正确,但随后出现错误。同时respond_to?
不正确,ObjectC.new.respond_to? :hello_a
返回false。
最后,添加这个类:
class ObjectD
include SaysHello
include SaysGoodbye
def respond_to?(method)
super.respond_to?(method) || !!(method.to_s =~ /^lol/)
end
def method_missing(method, *args, &block)
if (method.to_s =~ /^lol/)
puts "Haha, #{method}"
else
super.method_missing(method, *args, &block)
end
end
end
这个代码存在一些问题。ObjectD.new.lol_zzz
是可以工作的,但是 ObjectD.new.hello_a
和 ObjectD.new.goodbye_t
都会在输出正确字符串后抛出一个名称异常。同时,respond_to?
也无法识别 hello 和 goodbye 方法。
有没有一种方法可以让所有方法都正常工作?了解 method_missing
、模块和 super
之间的交互方式也会非常有用。
编辑:coreyward 解决了这个问题,如果在我定义的所有方法中使用 super
而不是 super.<method-name>(args...)
,程序就可以正常工作。不过我不明白为什么,所以我在这里提了另一个问题。