2012-06-24 18 views
10

Ostatnio natknąłem się na dziwne zachowanie z operatorem defined? używanym do sprawdzenia, czy słowo kluczowe super może być użyte w obecnym kontekście. Zwykle działa dobrze, ale kiedy próbowałem połączyć test z metaprogramowaniem, otrzymałem niespodziewane wyniki.Dziwne zachowanie zdefiniowanego? (Super) sprawdzenia

Łatwiej pokazują następnie opisują więc o to przykład destylowaną w celu zilustrowania problemu:

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

(A i AA klas mają zarówno .def_f! sposób klasę)

A.def_f! 

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

(A.f nie ma żadnych super i wysyłek do A.f, więc wszystko jest OK, ale ...)

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

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

Czy ktoś mógłby mi wytłumaczyć ostatnią linię? A.f nie ma super metody, a następnie dlaczego zwraca "super" zamiast nil? Czy to błąd?

(próbowałem go w 1.9.2 i 1.9.3-same wyniki)

UPD: Otworzyłem bilet na bugtracker Ruby: http://bugs.ruby-lang.org/issues/6644

+3

Po obejrzeniu źródeł Ruby, znalazłem tutaj prawdziwy błąd. Powinieneś zgłosić to do systemu śledzenia błędów Ruby. –

+1

A jeśli to zrobisz, nie zapomnij opublikować linku do problemu tutaj! ':)' –

+1

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

Odpowiedz

2

OK, więc @Niklas miał rację, zgłosiłem ten problem do robaka Ruby i potwierdzili i naprawili błąd: https://bugs.ruby-lang.org/issues/6644.

O ile mi wiadomo, poprawka zostanie dołączona do ruby ​​2.0.0.

+0

Dziękujemy za zgłoszenie i kontynuację! –

1

Tak istnieje kilka dziwactw z define_method , to nie jest problem z defined?(super) naprawdę, ale bardziej z define_method. Powiedziawszy to, za każdym razem, gdy napotykam taki przypadek skrajny z define_method, zwykle kończę eval'ing ciągiem kodu Ruby i zawsze kończy się on zgodnie z oczekiwaniami.

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 

Na pytanie dlaczego to działa w ten sposób, że nie jestem wystarczająco doświadczony ze źródła Ruby do wiem, może ktoś, kto wie więcej niż ja może dostroić się. Ale dla celów praktycznych, oceniając łańcuch zawsze pracował dla mnie.

+0

Nadal uważam, że problem jest bardziej związany z 'zdefiniowanym? (Super)', ale dzięki za obejście tego problemu. – Alexis