2013-03-04 21 views
5

Próbuję użyć metod refleksyjnych w Ruby i uruchomić zachowanie, które naprawdę mnie przerasta.Dlaczego Module.methods() i respond_to? działa inaczej w irb niż w skrypcie?

Poniższe przykłady wydaje się inaczej działa w IRB i po wywołaniu skryptu Ruby:

Przykład 1:

def myfun; end 
p respond_to?(:myfun) 

W IRB, to mówi 'prawdziwy', W skrypcie: 'false' .

Przykład 2:

ml = methods 
def myfun; end 
p methods - ml 

W IRB Mówi [: myfun]. W skrypcie: [].

Znalazłem to pod 1.8, 1.9 MRI, JRuby 1.5.6, itd. - więc zakładam, że to jest normalne.

Dlaczego różnica?

Byłem prawie pewien, że "odpowiedź"? jest sposobem sprawdzenia, czy dana metoda jest dostępna - dlaczego to nie działa w powyższym przypadku?

Odpowiedz

5

Ta funkcja - metoda na "głównym" obiekcie - jest zdefiniowana jako prywatna w skrypcie ruby. Można to sprawdzić w prosty sposób:

ml = private_methods 
def myfun; end 
p private_methods - ml #=> [:myfun] 
p respond_to?(:myfun, true) #=> true 

Jeśli nazywają to wyraźnie na siebie dostaniesz błąd:

self.myfun 
# NoMethodError: private method ‘myfun’ called for main:Object 

Z drugiej strony, w IRB metoda jest zdefiniowana jako społeczeństwa. Pod maską wygląda to mniej więcej tak:

class Object 
    def irb_binding 
    # this is where your entered code is evaluated 
    def myfun; :ok; end # you can define methods in other methods 
    self.myfun # and they are public by default 
    end 
end 

p irb_binding # :ok 

IRB może łatwo ocenić na najwyższym poziomie, ale zamiast tego tworzy osobny środowisko z metody tak, że zmienne lokalne nie są udostępniane:

require "irb" 
foo = :ok 
IRB.start 
#>> foo 
# NameError: undefined local variable or method `foo' for main:Object 

I uważam, że metody publiczne są przypadkowe z powodu wdrożenia i nie ma to większego znaczenia. Te metody są i tak przejściowe.

+0

Bardzo dobrze wiedzieć - to niesamowite, nie natknąłem się na to po latach ekspozycji Rubiego. Tak, interesuje mnie, dlaczego IRB sprawia, że ​​są publiczni, że stara się być bardziej przyjazny - czyż nie? :) Rozumiem, dlaczego zwykle są prywatne - aby uniknąć pomyłek takich jak "def f; end; class A; end; A.new.f", czy coś w tym stylu? – inger

+0

Byłem zaskoczony, gdy się tego nauczyłem. –

+0

@ Siemio Czy możesz wyjaśnić, dlaczego metody 'irb' są publiczne? A dlaczego w 'irb'' myfun' i 'self.myfun' odnosi się do tej samej metody? – codeit