2010-02-27 9 views
60

In Ruby, posso definire un metodo foo = (bar):In Ruby, come posso controllare se il metodo "foo =()" è definito?

irb(main):001:0> def foo=(bar) 
irb(main):002:1> p "foo=#{bar}" 
irb(main):003:1> end 
=> nil 

Ora mi piacerebbe verificare se è stata definita,

irb(main):004:0> defined?(foo=) 
SyntaxError: compile error 
(irb):4: syntax error, unexpected ')' 
from (irb):4 
from :0 

Qual è la sintassi corretta da usare Qui? Presumo che ci deve essere un modo per scappare "foo =" tale che sia analizzato e passato correttamente al definito? operatore.

risposta

104

Il problema è che il metodo foo= è progettato per essere utilizzato nelle assegnazioni. È possibile utilizzare defined? nel modo seguente per vedere cosa sta succedendo:

defined? self.foo=() 
#=> nil 
defined? self.foo = "bar" 
#=> nil 

def foo=(bar) 
end 

defined? self.foo=() 
#=> "assignment" 
defined? self.foo = "bar" 
#=> "assignment" 

Confronti che, per:

def foo 
end 

defined? foo 
#=> "method" 

Per verificare se il metodo foo= è definito, è necessario utilizzare respond_to? invece:

respond_to? :foo= 
#=> false 

def foo=(bar) 
end 

respond_to? :foo= 
#=> true 
+0

Grazie! Questo risolve il mio problema. Sono ancora curioso di sapere se c'è un modo per sfuggire a foo = in modo tale da poterlo alimentare a definito? ma almeno ora posso andare avanti. –

+1

Il problema qui è che 'foo =' è sempre usato nelle assegnazioni, quindi Ruby restituirà '" assegnazione "' se si prova per 'defined? foo() '(vedi risposta aggiornata). – molf

32

È possibile verificare se esiste un metodo utilizzando il metodo respond_to? e si passa ad esso un simbolo, ad esempio bar.respond_to?(:foo=) per vedere se l'oggetto bar ha un metodo foo=. Se vuoi sapere se le istanze di una classe rispondono a un metodo, puoi utilizzare method_defined? sulla classe (o sul modulo), ad es. Foo.method_defined?(:bar=).

defined? non è un metodo, ma un operatore che restituisce una descrizione dell'operando (o zero se non è definito, motivo per cui può essere utilizzato in un'istruzione if). L'operando può essere qualsiasi espressione, cioè una costante, una variabile, un assegnamento, un metodo, una chiamata al metodo, ecc. Il motivo per cui non funziona quando si esegue defined?(foo=) è a causa delle parentesi, salta e dovrebbe funzionare più o meno come previsto. Detto questo, defined? è un operatore piuttosto strano, e nessuno lo usa per verificare l'esistenza dei metodi.

+0

È respond_to ?, non risponde_to? – 0x4a6f4672

+3

Ah, l'ortografia della libreria principale di Ruby ... 'answer_to?', 'Start_with?', 'End_with?'. – Theo

+1

http://stackoverflow.com/questions/5280556/why-does-ruby-use-respond-to-instead-of-responds-to ha una bella spiegazione della scelta dietro la denominazione TL; DR 'you.knock se you.respond_to? (: battere) ' – drewish

Problemi correlati