2012-06-24 11 views
10

Últimamente me encontré con un comportamiento extraño con el operador defined? utilizado para comprobar si super palabra clave puede ser utilizado en el contexto actual. Normalmente funciona bien, pero cuando traté de combinar la comprobación defined? super con un poco de metaprogramación, me dio resultados inesperados.extraño comportamiento de definido? (Super) comprobar

Es más fácil para mostrar a continuación, para describir, por lo que aquí es un ejemplo destilada para ilustrar el problema:

class A; 
    def self.def_f!; 
    singleton_class.send(:define_method, :f) { defined? super } 
    end 
end 
class AA < A; end 

(A y AA clases ambos tienen .def_f! método de clase)

A.def_f! 

A.f # => nil 
AA.f # => nil 

(A.f no tiene envíos súper y AA.f a A.f, entonces todo está bien hasta ahora, pero ...)

AA.def_f! # define its own .f method in the AA class 

AA.f # => "super" 
A.f # => "super" # WHY??? 

¿Alguien podría explicarme la última línea? A.f no tiene un método estupendo, ¿por qué devuelve "super" en lugar de nil? ¿Es un error?

(Lo he probado en 1.9.2 y 1.9.3 del mismo resultados)

UPD: me abrió un billete en el bugtracker Ruby: http://bugs.ruby-lang.org/issues/6644

+3

Después de mirar las fuentes de Ruby, creo que encontraste un error real aquí. Debes informarlo al rastreador de errores de Ruby. –

+1

Y si lo hace, ¡no olvide poner un enlace al problema aquí! ':)' –

+1

@NiklasB. Hecho: http://bugs.ruby-lang.org/issues/6644 – Alexis

Respuesta

2

Ok, entonces @Niklas tenía razón, informé de este problema al rastreador de errores de Ruby y confirmaron y corrigieron el error: https://bugs.ruby-lang.org/issues/6644.

Por lo que he entendido, la solución se incluirá en ruby ​​2.0.0.

+0

¡Gracias por informar y por el seguimiento! –

1

Sí hay algunas peculiaridades con define_method , esto no es un problema con defined?(super) realmente, pero más con define_method. Habiendo dicho eso, cada vez que encuentro un caso de borde como este con define_method, generalmente termino evaluando una cadena de código de Ruby y siempre termina funcionando como se esperaba.

module M; 
    def def_f! 
    singleton_class.class_eval <<-RUBY 
     def f 
     defined?(super) 
     end 
    RUBY 
    end 
end 

class A; extend M; end 
class AA < A; end 

A.def_f! 

p A.f # => nil 
p AA.f # => nil 

AA.def_f! # define its own .f method in the AA class 

p AA.f # => "super" 
p A.f # => nil 

En cuanto a por qué funciona de esta manera, no tengo experiencia suficiente con la fuente de Ruby saber, tal vez alguien que sabe más que yo pueda intervenir. Sin embargo, para efectos prácticos, la evaluación de una cadena siempre ha trabajado para mi.

+0

Todavía creo que el problema es más con 'defined? (Super)', pero gracias por la solución. – Alexis