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?

Author: Community, 2010-04-08

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

 61
Author: JRL,
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.

 18
Author: Jörg W Mittag,
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" /

 11
Author: yfeldblum,
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.

 2
Author: bvrwoo_3376,
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.

 0
Author: Andrew,
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