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