2010-02-27 10 views
60

En Ruby, que puede definir un método foo = (bar):En Ruby, ¿cómo puedo verificar si el método "foo =()" está definido?

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

Ahora me gustaría comprobar si se ha definido,

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

Cuál es la sintaxis correcta de usar ¿aquí? Supongo que debe haber una forma de escapar de "foo =" de manera que se analice y pase correctamente a lo definido. operador.

Respuesta

104

El problema es que el método foo= está diseñado para ser utilizado en asignaciones. Puede utilizar defined? de la siguiente manera de ver lo que está pasando:

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

def foo=(bar) 
end 

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

que para comparar:

def foo 
end 

defined? foo 
#=> "method" 

Para probar si se define el método foo=, se debe utilizar respond_to? lugar:

respond_to? :foo= 
#=> false 

def foo=(bar) 
end 

respond_to? :foo= 
#=> true 
+0

Gracias! Esto resuelve mi problema. Sigo teniendo curiosidad por saber si hay una forma de escapar de foo = tal que se pueda alimentar a definido. pero al menos ahora puedo seguir. –

+1

El problema aquí es que 'foo =' siempre se usa en las asignaciones, por lo que Ruby devolverá '" asignación "' si prueba '¿definido? foo() '(ver respuesta actualizada). – molf

32

Puede verificar si existe un método utilizando el método respond_to?, y le pasa un símbolo, por ejemplo bar.respond_to?(:foo=) para ver si el objeto bar tiene un método foo=. Si desea saber si las instancias de una clase responden a un método, puede usar method_defined? en la clase (o módulo), p. Foo.method_defined?(:bar=).

defined? no es un método, sino un operador que devuelve una descripción del operando (o nulo si no está definido, por lo que se puede utilizar en una sentencia if). El operando puede ser cualquier expresión, es decir, una constante, una variable, una asignación, un método, una llamada a un método, etc. La razón por la que no funciona cuando se hace defined?(foo=) es debido a los paréntesis, sáltelos y debería funcionar más o menos como se esperaba Dicho esto, defined? es un operador bastante extraño, y nadie lo usa para probar la existencia de métodos.

+0

¿Es respond_to ?, no responde_ a? – 0x4a6f4672

+3

Ah, la ortografía de la biblioteca central de Ruby ... 'responder_a?', 'Start_with?', 'End_with?'. – Theo

+1

http://stackoverflow.com/questions/5280556/why-does-ruby-use-respond-to-instead-of-responds-to tiene una buena explicación de la elección detrás del nombre TL; DR 'you.knock if you.respond_to? (: knock) ' – drewish

Cuestiones relacionadas