Jako ćwiczenie programistyczne napisałem fragment kodu Ruby, który tworzy klasę, tworzy dwa obiekty z tej klasy, monkeypatches jeden obiekt i polega na metodzie method_missing do monkeypatch drugiej.Ruby: define_method vs. def
Oto umowa. To działa zgodnie z przeznaczeniem:
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
Zauważysz, że mam parametr method_missing. Zrobiłem to, ponieważ miałem nadzieję użyć metody define_method do dynamicznego tworzenia brakujących metod o odpowiedniej nazwie. Jednak to nie działa. W rzeczywistości, nawet przy użyciu define_method z nazwą statycznej tak:
def method_missing(m)
puts "No #{m}, so I'll make one..."
define_method(:screech) do
puts "This is the new screech."
end
end
Koniec z następującym wynikiem:
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.
Co sprawia, że komunikat o błędzie bardziej zdumiewające jest to, że mam tylko jeden argument dla method_missing
. ..
To wspaniała odpowiedź, Avdi, i wyjaśnia kilka innych pytań, które miałem. Dziękuję Ci. – gauth
Zasadniczo pokazuje to, dlaczego zawsze powinieneś: a) używać białej listy w 'method_missing', abyś * tylko * obsługiwał metody, którymi jesteś * faktycznie * zainteresowany, i b) przekazywał wszystko, co robisz * nie * chce obsłużyć "w górę łańcucha pokarmowego", używając "super". –
@ JörgWMittag mogę mieć więcej słów na linii * b) przekazać wszystko, czego nie chcesz obsługiwać "w górę łańcucha pokarmowego", używając super. ? * –