Ruby Language
method_missing
Sök…
parametrar
Parameter | detaljer |
---|---|
metod | Namnet på metoden som har kallats (i exemplet ovan är detta :say_moo , notera att det här är en symbol. |
* args | Argumenten som skickats till denna metod. Kan vara valfritt nummer eller ingen |
&blockera | Blocket för den metod som kallas, detta kan antingen vara ett do block eller ett { } slutet block |
Anmärkningar
Ring alltid super, längst ner i den här funktionen. Detta sparar tyst misslyckande när något anropas och du inte får något fel.
Till exempel kommer den här metoden att missa orsaka problem:
class Animal
def method_missing(method, *args, &block)
say, speak = method.to_s.split("_")
if say == "say"
speak
end
end
end
=> Animal.new.foobar
=> nil # This should really be raising an error
method_missing
är ett bra verktyg att använda när det är lämpligt, men har två kostnader du bör tänka på. Först, method_missing
är mindre effektiv - rubin måste söka i klassen och alla dess förfäder innan den kan falla tillbaka på denna metod; denna prestationsstraff kan vara trivial i ett enkelt fall, men kan lägga till. För det andra är detta en form av metaprogrammering som har stor makt som har ansvaret för att se till att implementeringen är säker, hanterar skadliga insatser, oväntade ingångar och så vidare.
Du bör också åsidosätta respond_to_missing?
såhär:
class Animal
def respond_to_missing?(method, include_private = false)
method.to_s.start_with?("say_") || super
end
end
=> Animal.new.respond_to?(:say_moo) # => true
Att fånga samtal till en odefinierad metod
class Animal
def method_missing(method, *args, &block)
"Cannot call #{method} on Animal"
end
end
=> Animal.new.say_moo
> "Cannot call say_moo on Animal"
Med hjälp av den saknade metoden
class Animal
def method_missing(method, *args, &block)
say, speak = method.to_s.split("_")
if say == "say"
speak
else
super
end
end
end
=> a = Animal.new
=> a.say_moo
=> "moo"
=> a.shout_moo
=> NoMethodError: undefined method `shout_moo'
Använd med block
class Animal
def method_missing(method, *args, &block)
if method.to_s == 'say'
block.call
else
super
end
end
end
=> Animal.new.say{ 'moo' }
=> "moo"
Använd med parameter
class Animal
def method_missing(method, *args, &block)
say, speak = method.to_s.split("_")
if say == "say" && speak
return speak.upcase if args.first == "shout"
speak
else
super
end
end
end
=> Animal.new.say_moo
=> "moo"
=> Animal.new.say_moo("shout")
=> "MOO"