プログラミングの練習として、クラスを作成し、そのクラスから2つのオブジェクトをインスタンス化し、1つのオブジェクトにモンキーパッチを適用し、もう1つにmonkeypatchを行うmethod_missingに依存するRubyスニペットを書きました。
これが取引です。これは意図したとおりに機能します。
class Monkey
def chatter
puts "I am a chattering monkey!"
end
def method_missing(m)
puts "No #{m}, so I'll make one..."
def screech
puts "This is the new screech."
end
end
end
m1 = Monkey.new
m2 = Monkey.new
m1.chatter
m2.chatter
def m1.screech
puts "Aaaaaargh!"
end
m1.screech
m2.screech
m2.screech
m1.screech
m2.screech
Method_missingのパラメーターがあることに気付くでしょう。 define_methodを使用して、適切な名前で欠落しているメソッドを動的に作成することを望んでいたため、これを行いました。ただし、機能しません。実際、次のような静的な名前でdefine_methodを使用しても:
def method_missing(m)
puts "No #{m}, so I'll make one..."
define_method(:screech) do
puts "This is the new screech."
end
end
次の結果で終了します。
ArgumentError: wrong number of arguments (2 for 1)
method method_missing in untitled document at line 9
method method_missing in untitled document at line 9
at top level in untitled document at line 26
Program exited.
エラーメッセージをさらに混乱させるのは、method_missing
...の引数が1つしかないことです。
define_method
は、オブジェクトの(プライベート)メソッドですClass。 instanceから呼び出しています。 define_method
と呼ばれるインスタンスメソッドがないため、method_missing
(今回は:define_method
(欠落しているメソッドの名前)、および:screech
(唯一の引数)で再帰します。 define_method
)に渡しました。
代わりにこれを試してください(すべてのMonkeyオブジェクトで新しいメソッドを定義するには):
def method_missing(m)
puts "No #{m}, so I'll make one..."
self.class.send(:define_method, :screech) do
puts "This is the new screech."
end
end
または、これ(オブジェクトの「固有クラス」を使用して、呼び出されるオブジェクトでのみ定義する):
def method_missing(m)
puts "No #{m}, so I'll make one..."
class << self
define_method(:screech) do
puts "This is the new screech."
end
end
end
define.methodはプライベートメソッドであるため、self.class.define_method(:screech)は機能しません。
class << self
public :define_method
end
def method_missing(m)
puts "No #{m}, so I'll make one..."
Monkey.define_method(:screech) do
puts "This is the new screech."
end
def method_missing(m)
self.class.class_exec do
define_method(:screech) {puts "This is the new screech."}
end
end
screechメソッドは、すべてのMonkeyオブジェクトで使用できます。