2010-04-08 19 views
41

this discussion'den esinlenerek, biraz googling yaptıktan sonra Ruby'deki yöntemlerle ilgili oldukça basit bir soruyu yanıtlayamadım: yöntem nesneleri mi var ya da değil mi?Ruby'de Yöntemler: nesneler değil mi?

Farklı görüşler vardır here ve there, ve gerçekten derinlemesine bir açıklama duymak isterim. 'Ben diğer taraftan, bir yöntem adı alır ve bir Method örneğini döndürür, ancak Object#method yöntemin, farkındayım

, sen Proc durumlarda bunları yapmak blokları ile yapabilirsiniz benzer bir şey var, ve bloklar değiller t nesneleri, yani yöntemleri farklı kılan nedir?

+0

Fonksiyonlar Ruby'de birinci sınıf vatandaşlardır ve nesnelere dönüştürülebilir, o zaman neden endişelenirsiniz? Bence cevap çok mantıklı olacak kadar düşük seviyelerde olacak ... –

+3

Onlar? IMHO, onları nesnelere dönüştürmeniz gereken şey onları birinci sınıf değil yapar. Cevaplardan da öğrenmek istediğim şey buydu. –

cevap

60

Yöntemleri Ruby'nin sözdizimi temel bir parçası, ancak Ruby programları üzerinde çalışabilir değerleri değildir. Yani, Ruby'nin yöntemleri, nesnesinin dizeleri, dizeleri ve sayıları ve dizileri değildir. Bu, belirli bir yöntemi, temsil eden bir yöntem nesne elde etmek üzere, ancak, mümkün olan olduğunu ve Yöntem nesneler aracılığıyla dolaylı olarak yöntem çağırabilir. The Ruby Programming Language itibaren

:
alt text http://ecx.images-amazon.com/images/I/517LDwIEYwL._SL75_.jpg

+0

Merhaba, Yöntemler nesne değilse, nasıl mümkün olabilir? 'irb (ana): 015: 0> def hi IRB (ana): 016: (ana) 1> "Merhaba" IRB 017: 1> uç => nil IRB (ana): 018: 0> hi.object_id => 22.452.528 IRB (ana): 019: 0> hi.object_id.send hi => "merhaba" IRB (ana): 020: 0> hi.object_id.send (hi) => "merhaba" ' –

+11

' hi.object_id', önce 'hi' yöntemini çağırır ve sonucunun object_id'ini döndürür (" merhaba "' dır). –

10

Ruby'de, yöntemler ve bloklar, kendi başlarına, yerel veya birinci sınıf nesneler değildir. Bununla birlikte, nesneler, genellikle hiçbir fark yaratmayacak şekilde çok kolay bir şekilde sarılabilirler.

Ama denemek ve akılda sonucunu tutmak, Haskell'de

a = Object.method(:new).object_id 
b = Object.method(:new).object_id 
a == b 
=> false 

(numaralı yanı sıra lambdas ve fonksiyonlar dahil) tüm değerleri birinci sınıf değerleridir. Dilin her yönü, hepsi eşit olarak tedavi edilir. Bu Ruby'de durum böyle değil, ancak yaklaşık olabilir.

+0

Adalet, sizin argümanınız benimkiyle aynıydı. Buna ek olarak, yöntemleri döndürmenin başka bir yolunun farkında değilim, bu nedenle #method (method_name), bir yönteme referans olarak başvurmanın tek yolu gibi görünüyor. –

+1

object_id'inizin kanıtladığı tek şey, onların doğrudan olmadıklarıdır. 'a = 1.0.object_id; b = 1.0.object_id; a == b # => false ' –

18

Gerçekten söyleyemem.

Bir yönteme erişim elde etmenin tek yolu, Method nesnesini döndürecek olan bazı nesneye #method iletisini göndermektir. Ama bu Method yönteminin kendisi mi? Yoksa yöntem etrafında bir sarıcı mı? Yoksa orijinal yöntemin dönüştürülmüş bir versiyonu mu?

Bilmiyorsunuz: Bir yönteme bakmak istiyorsanız, numaralı telefonu arayarak, bir nesne alacaksınız. Ne önce neydi, #method aradınız, bu yüzden size söyleyemezsiniz.

Birkaç veri noktası: Ruby'de her şey bir değer döndürür. def ne döndürüyor? Bu hep döner nil değil, bir Method nesnesi. Ve define_method? Bu bir Proc ama bir Method (ne de bir UnboundMethod) döndürür. [Not: Rubinius olarak, def hala Method nesne olup yöntemin derlenmiş bayt kodu verir, ancak.]

Ruby Language Spesifikasyonu'nun 6.1. Bölümü'nün 4. ve 5. paragraflarına bakarsanız (satırlar 29-34 ve 1-5 arası sayfa 5 ve 6), yöntemler arasında bir ayrım olduğunu açıkça görebilirsiniz. ve nesneler. Ve yerleşik sınıfların özelliklerine bakarsanız, ne Method ne de UnboundMethod'un ne olduğunu ve ne de Object#method olduğunu göreceksiniz. IOW: yönteminin nesnesi olmayan standartlara uygun bir Ruby yorumlayıcısı oluşturabilirsiniz.

Şimdi, OTOH blokları kesinlikle nesnesi değil. Orada özgün blok (lambda, proc, Proc.new, & desen) ile aynı davranış bloklardanProc nesneler oluşturmak için birçok yol vardır, ancak, blokların nesneler değildir.

Bunu şu şekilde düşünün: Bir dosya nesnesini oluşturmak için bir dizeyi File.new geçirebilirsiniz, ancak bu bir dosya dizisi oluşturmaz. Bir proc nesnesi oluşturmak için bir bloğu Proc.new'a geçirebilirsiniz, ancak bu bir proc oluşturmaz.

+0

Sadece referans için: http://stackoverflow.com/questions/4294485/how-do-i-reference-a-function-in-ruby/4294660#4294660 –

+2

Alaycı olmak istemeyen, ama bir blok nedir? .rb dosyasında sadece bir metin parçası mı? –

+0

Jörg, Ruby yöntemlerinin daha sonraki bir StackOverflow sorusu nesnesi olmadığını açıkladı @ MladenJablanović linkleri. Alıntı şu şekildedir: "Ancak, Metot ve UnboundMethod, yöntemin kendisi değil, yöntem etrafındaki sarmalayıcılardır. Yöntemler, Ruby'de nesne değildir. (Diğer cevaplarda yazdığımın tersine, BTW. Gerçekten ihtiyacım var. geri gitmek ve düzeltmek için.) " – Powers

2

Nesneler ve Yöntemler, yöntemlerin dönüş değeri bir nesne değil, bir sayı ise bile, aynı değildir. Nesneler bir yöntemde, lambda veya proc kapsamı dışında yığın üzerinde yaşar ve yöntemin kendisi yığın üzerinde yaşar ve statik ve sınıf nesneleri yığın üzerinde tahsis edilirken yorumlandıktan sonra bir adres atama vardır. Ruby hala onu yorumlamak ve VALUE yapısına aktarmak için C kullanır.

+2

Ruby'nin bakış açısından Yöntemler Nesnelerdir. Uygulama detayları önemli değildir. Bir yöntem, başka herhangi bir nesne gibi adreslenebilir ve iletilebilir. Procs ayrıca Nesnelerdir (ve bloklar bir Proc/lambda yaratmanın sözdizimsel bir yoludur). – simonmenke

0

Parantez, yakutta isteğe bağlı olduğundan, yöntem nesneleri genellikle method yöntemiyle yöntem nesnesini açıkça almanız gereken anlamda "gizlenir". Ancak, bir metod nesnesini yakalama çabasını yaparsanız, bir nesne gibi davrandığını açıkça ortaya koyar. Ruby> = 2.1'den beri, her zamankinden daha avantajlı olmak daha kolaydır. Bir için

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 

See this gist:

Örneğin, sizin yöntemler onlar şöyle (hayır parens yöntemi nesnesidir ve parens yöntemi çağırmak için kullanılır) JavaScript yapmak daha gibi davranmaya alabilirsiniz Bu örnek ile test olarak yazılmıştır.

JRL's answer

yöntemleri vb
olan dizeleri gibi nesneleri değildir, ancak yöntem nesneleri Pars daha gerçek ve diğer olduklarını söyleyerek Matz kitabı tırnak/no-parens şey onlar hemen hemen başka yakut nesne gibi hareket ederler. Bu bir duck-typed language, bu yüzden kitabımda nesneleri nesne olarak nitelendirdiğimi söyleyebilirim.