メソッドの欠落を拡張するモジュールがいくつかあります。
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_theretrue を返します。
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_aand ObjectD.new.goodbye_tは両方とも、正しい文字列を出力した後に名前の例外をスローします。respond_to?hello および goodbye メソッドでも失敗します。
これをすべて正しく機能させる方法はありますか? method_missing、 モジュール 、がどのように相互作用しているかについての説明superも非常に役立ちます。
編集: coreyward が問題を解決しsuper.<method-name>(args...)ました。定義したすべてのメソッドの代わりに super を使用すると、プログラムは正しく動作します。これがなぜなのかわからないので、これについて別の質問をしましたsuper.<method-name> do in ruby?