2013-02-06 9 views
8
class A 
    def test 
     "Test from instance" 
    end 
    class << self 
     def test 
      "Test from class" 
     end 
    end 
end 

p A.send(:test) # "Test from class" 
p A.new.method(:test).call # "Test from instance" 

Oto symbol działa zgodnie z oczekiwaniami, ale tutaj:Zrozumienie Ruby symbol jako wywołanie metody

s="test" 
s1=:s 
p s1 # :s 

dlaczego : s drukowany jest tutaj ?? Nie rozumiem powodu, który za tym stoi. Czy ktoś może mi wyjaśnić?

Odpowiedz

2

Ustawiasz wartość s1 na: s, więc dlaczego miałbyś oczekiwać, że zwróci coś innego?

Jeśli spojrzysz na API ruby ​​dla klasy Object, zobaczysz zarówno Object#send jak i Object#method jako symbol, a więc najwyższy przykład jest również całkowicie oczekiwany.

3

Od https://stackoverflow.com/a/1255362/509710:

p foo robi wkłada foo.inspect, tzn drukuje wartość inspect zamiast to_s, który jest bardziej odpowiedni do debugowania (bo można np odróżnić 1, "1" i "2\b1", który cię nie można podczas drukowania bez kontroli).

+0

Hej, teraz to rozumiem ... to było głupie ze mnie, nie znam różnicy między p i puts.Dzięki – sunny1304

14

Symbole są rodzajem lekkich ciągów (choć nie są one ciągami). Metody i method() mogą przyjmować łańcuchy lub symbole; jeden jest konwertowany na drugi w wewnętrznych operacjach (nie wiem, który), a następnie ruby ​​wykonuje metodę z pasującą nazwą. Stąd A.send(:text) jest odpowiednikiem A.text(). Jeśli masz zmienną o nazwie methodName = :text, możesz zrobić A.send(methodName), ale nie A.methodName().

Symbole nie są zmiennymi, więc nie można przypisać wartości do symbolu. W twoim przykładzie symbol :s jest niezwiązany ze zmienną s (pomimo faktu, że mają tę samą "nazwę", poprzedzając ją dwukropkiem czyni ją symbolem zamiast zmiennej). Przypisujesz wartość ciągu do zmiennej s, ale nakazujesz jej wydrukować symbol, który to robi.

+0

To jest odpowiedź (powiedział niechętnie) – DanSingerman

0

Symbole są po prostu szczególnym rodzajem struny, który jest bardziej wydajny, aby radzić sobie z runtime. to jest to! Nie są to metody lub zmienne ani nic takiego.

Kiedy robisz A.send(:test), wszystko, co robisz, mówi "hej, A, zadzwoń do metody o nazwie" test "". Nie wysyłasz samej metody, tylko nazwę; to logika wewnątrz send, która jest odpowiedzialna za wyszukiwanie właściwej metody wywoływania.

To samo dotyczy pytania o metodę z A.new.method(:test). Wszystko, co przechodzisz na numer method, to nazwa "test", a nie metoda określona jako "test". To jest do method, aby użyć nazwy i znaleźć rzeczywistej metody, dzięki czemu można go zwrócić, i to jest ta wartość zwracana - obiekt Metoda - który robisz call na. Nie można wykonać call na Symbolie takim jak :test, ponieważ jest to tylko nazwa.

2
s="test" 
s1=:s 
p :s.object_id #137448 
p s.object_id #77489950 
p s1.object_id #137448 

Teraz rozumiem to. Przypisałem symbol, ale spodziewałem się napisu.