Рубин: определение метода и деф
в качестве упражнения по программированию я написал фрагмент Ruby, который создает класс, создает два объекта из этого класса, monkeypatches один объект и полагается на method_missing для monkeypatch другой.
вот в чем дело. Это работает по назначению:
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
...
3 ответа:
define_method
является (частным) методом объекта класс. Вы вызываете его из экземпляр. Не существует метода экземпляра с именемdefine_method
, поэтому он возвращается в свойmethod_missing
С:define_method
(имя метода), и:screech
(единственный аргумент, который вы передалиdefine_method
).попробуйте вместо этого (чтобы определить новый метод для всех объектов обезьяна):
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
или это (чтобы определить его только на объекте он называется при использовании объекта "eigenclass"):
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