Metody w Ruby: obiekty czy nie?
Zainspirowany tą dyskusją, Po jakimś googlowaniu nie byłem w stanie znaleźć odpowiedzi na dość proste pytanie dotyczące metod w Rubim: czy metody są obiektami czy nie?
Istnieją różne opinie tutaj i tam, i naprawdę chciałbym usłyszeć, powiedzmy, dogłębne wyjaśnienie.
Znam metodę Object#method
, która pobiera nazwę Metody i zwraca instancję Method
, ale z drugiej strony, jest podobna rzecz, którą można zrobić z blokami do przekształcić je w instancje Proc
, a bloki nie są obiektami, więc co sprawia, że metody są inne?
5 answers
Metody są podstawową częścią Składni Ruby, ale nie są to wartości na którym mogą działać programy Ruby. Czyli metody Rubiego nie są objects in the way that strings, liczby, a tablice są. On możliwe jednak uzyskanie metody obiekt, który reprezentuje daną metodę, i możemy powoływać się na metody pośrednio poprzez obiekty metody.
Z języka programowania Ruby:
alt text http://ecx.images-amazon.com/images/I/517LDwIEYwL._SL75_.jpg
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-08 18:33:59
Nie wiadomo.
Jedynym sposobem uzyskania dostępu do metody jest wysłanie wiadomości #method
do jakiegoś obiektu, który następnie zwróci obiekt Method
. Ale czy to Method
jest obiektem samej metody? A może jest to owijka wokół metody? A może jest to przekonwertowana wersja oryginalnej metody?
Nie możesz wiedzieć: jeśli chcesz spojrzeć na metodę, musisz wywołać #method
, w którym momencie na pewno otrzymasz obiekt. Co to było przed zadzwoniłeś #method
nie możesz patrzeć, więc nie możesz powiedzieć.
Kilka datapointów: w Rubim wszystko zwraca wartość. Co zwraca def
? To zawsze zwraca nil
, a nie Method
obiekt. I define_method
? Zwraca Proc
, ale nie Method
(ani UnboundMethod
). [Uwaga: w Rubinius, def
zwraca skompilowany bajt kodu metody, ale nadal nie jest obiektem Method
.]
Jeśli spojrzysz na 4. i 5. paragraf sekcji 6.1 specyfikacji języka Ruby (linie 29-34 i 1-5 NA strony 5 i 6), widać wyraźnie, że istnieje rozróżnienie między metodami i obiektami. Jeśli spojrzysz na specyfikację wbudowanych klas, przekonasz się, że ani Method
, ani UnboundMethod
nie są tam, ani Object#method
. IOW: możesz zbudować doskonale zgodny ze standardami interpreter Ruby, w którym metody nie są obiektami.
Teraz bloki na pewno nie są obiektami. Istnieje wiele sposobów, aby skonstruować Proc
obiektów z bloków, które następnie mają takie samo zachowanie jak oryginalny blok (lambda
, proc
, Proc.new
, sigil &
), ale same bloki nie są obiektami.
Pomyśl o tym w ten sposób: możesz przekazać łańcuch znaków do File.new
, aby skonstruować obiekt file, ale to nie czyni łańcucha plikiem. Można przekazać blok do Proc.new
, aby skonstruować obiekt proc, ale to nie czyni bloku proc.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-08 19:38:33
W Rubim metody i bloki nie są same w sobie natywnymi lub pierwszorzędnymi obiektami. Jednak bardzo łatwo można je owinąć w przedmioty, tak że na ogół nie robi to różnicy.
Ale wypróbuj i pamiętaj o wyniku,
a = Object.method(:new).object_id
b = Object.method(:new).object_id
a == b
=> false
W Haskell wszystkie wartości (w tym liczby, a także lambda i funkcje) są wartościami pierwszej klasy. W każdym aspekcie języka wszystkie są traktowane równoważnie. W Ruby tak nie jest, ale może być / align = "left" /
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-19 12:50:53
Obiekty i metody nie są takie same, nawet jeśli wartością zwracaną dla metod jest obiekt, a nie nil. Obiekty żyją na stercie, chyba że w metodzie, lambda lub proc scope, a sama metoda żyje na stosie i ma przypisany adres po interpretacji, podczas gdy obiekty statyczne i klasowe są przydzielane na stercie. Ruby nadal używa C do interpretacji i przekazywania go do struktury wartości.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-17 14:25:03
Ponieważ nawiasy są opcjonalne w Rubim, obiekty metody są ogólnie "ukryte" w tym sensie, że musisz jawnie pobrać obiekt metody za pomocą metody method
. Jeśli jednak podejmiesz próbę przechwycenia obiektu metody, staje się jasne, że działa on jak obiekt. Od Ruby > = 2.1 jest to łatwiejsze do wykorzystania niż kiedykolwiek.
Na przykład, możesz sprawić, aby metody zachowywały się bardziej jak w Javascript (gdzie nie ma parens to obiekt metody, a parens są używane do wywołanie metody) w ten sposób:
foo = method def foo
def a(num)
3 * num.to_i
end
n = yield if block_given?
a(n || 3)
rescue
"oops!"
end
def foo.bar(num)
a(num)
end
foo.class #=> Method
foo() #=> 9
foo.call #=> 9
foo.call{2} #=> 6
foo(){2} #=> 6
foo.call{ raise "blam!" } #=> "oops!"
foo.bar(5) #=> 15
Zobacz ten gist dla wersji z tym przykładem zapisanym jako testy.
Odpowiedź JRL cytuje książkę Matz mówiącą, że metody nie są obiektami jak łańcuchy itp. są, ale obiekty metody są prawdziwe i inne niż parens/no-parens działają prawie jak każdy inny obiekt ruby. Jest to język kaczy , więc powiedziałbym, że kwalifikuje metody jako obiekty w mojej książce.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:09:56