Ruby Language
method_missing
Ricerca…
Parametri
Parametro | Dettagli |
---|---|
metodo | Il nome del metodo che è stato chiamato (nell'esempio precedente si tratta di :say_moo , si noti che questo è un simbolo. |
* args | Gli argomenti passati a questo metodo. Può essere qualsiasi numero o nessuno |
&bloccare | Il blocco del metodo chiamato, può essere un blocco do o un blocco { } chiuso |
Osservazioni
Chiama sempre super, in fondo a questa funzione. Ciò consente di risparmiare un errore silenzioso quando viene chiamato qualcosa e non si riceve un errore.
Ad esempio, questo metodo_missing causerà problemi:
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
è un buon strumento da usare quando appropriato, ma ha due costi da considerare. In primo luogo, method_missing
è meno efficiente: ruby deve cercare la classe e tutti i suoi antenati prima di poter method_missing
a questo approccio; questa penalizzazione delle prestazioni può essere banale in un caso semplice, ma può sommarsi. Secondo e più ampiamente, questa è una forma di meta-programmazione che ha un grande potere che viene fornito con la responsabilità di assicurare che l'implementazione sia sicura, gestisce correttamente input dannosi, input inaspettati e così via.
Dovresti anche ignorare respond_to_missing?
così:
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
Cattura di chiamate a un metodo indefinito
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"
Usando il metodo mancante
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'
Utilizzare con blocco
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"
Utilizzare con parametro
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"