2016-01-17 13 views
6

Method#unbind ve UnboundMethod#bind'un amacı nedir? Ben SomeClass kapsamında olup olmadığımıRuby'de bağlama/çözme yöntemlerinin amacı nedir?

class SomeClass 
    def a_method; puts "from SomeClass"; end 
end 

s = SomeClass.new 
s.a_method # => "from SomeClass" 

ben a_method çağırabilirsiniz: metotları kendi alıcısına kapsamına bağlı dışında ne toplamak itibaren

, yöntemler procs ve lambdas gibi çağrılabilir nesneler, veya SomeClass bir nesneyim varsa. Ben Method nesne olarak yöntemini çıkararak bir çağrılabilir nesne yapabilirsiniz, ama yine de bu örnekte sınıfın SomeClass bir nesneye kaçınılmazdır:

m = s.method :a_method 
m.class # => Method 
m.owner # => SomeClass 
m.call # => "from SomeClass" 

Neden unbind olan alıcıdan bir yöntemi isteyeyim? Belki bunu etrafa veya bind'u yeni bir bağlam vererek farklı bir nesneyle geçirebilirim, belki de bu yöntemi miras almadan tamamen farklı bir nesneye çağırabilirim, ama onun bir nesnesine bağlanmadıkça onunla hiçbir şey yapamam. orijinal sınıf veya I (yöntemlerden yana, gerçekten bir lambda ve lambda'lar biraz benzer) bir Proc nesneye dönüştürmek:

# Module#instance_method gives me an UnboundMethod 
ub = SomeClass.instance_method :a_method 
ub.class # -> UnboundMethod 

# now I can't make any calls 
ub.call # -> NoMethod Error, undefined method 'call' 

class AnotherClass; end 
a = AnotherClass.new 
b = ub.bind(a) # -> TypeError: bind argument must be an instance of SomeClass 
b = ub.bind(SomeClass.new).call # -> "from SomeClass" 

bir proc haline yöntem nesne dönüştürmek ve belki onunla bir şeyler yapabilirdi:

AnotherClass.class_eval do 
    # I can access m becausec this block is evaluated in the same 
    # scope it's defined, so I can grab m ;) 
    define_method(:method_from_some_class, m.to_proc) 
end 

AnotherClass.instance_methods(false) # -> [:method_from_some_class] 
a.method_from_some_class # -> "from SomeClass" 

Bunu yapmanın amacı nedir? Böyle bir şey için gerçek dünya uygulamaları nelerdir?

+0

Welp ... http://stackoverflow.com/questions/33708250/what-is-the-point-of-rubys-method-unbinding-mechanism – ndn

+1

Yaptıklarını anlıyorum ama şunu söyleyeceğim Zaman zaman yansıtıcı metaprorgram zekası da dahil olmak üzere 8 yıllık ruby ​​programlama, 'bağlanmayan bir yöntemde bind' kullanmak zorunda kalmam ya da hiç ilişkisiz bir yöntemle çok fazla şey yapmadım. Nadiren ihtiyaç duyuyorlar. Ama iyi ki yakutta tam bir yansıtma kontrolü için oradalar. Yine de onlar için bir kullanım görmüyorsanız, kullanımınız, sahip olduğunuzda bileceğiniz zor şeyler için nadirdir. Günlük araç kutusunun bir parçasıysa, muhtemelen çok akıllısınız demektir. – jrochkind

cevap

6

Gerçekten, meta programlamasında kullanışlıdır. SomeClass#method için kaynak kodun yerini bilmek istediğinizi varsayalım. SomeClass örneğini oluşturabilirseniz, yöntemin bazı meta verilerini araştırmak için çeşitli yöntemleri çağırabileceğiniz bir SomeClass örneğinde bunun bir (sınırlı) yöntem örneği oluşturabilirsiniz. Ancak, SomeClass#new'un yöntem imzasını bilmiyorsanız ya da SomeClass'un yapıcı metodu SomeClass#new'dan farklıysa ne olurdu? Sadece SomeClass örneğini güvenli bir şekilde oluşturmak zor olabilir. Bu ilişkisiz yöntem kullanışlı geliyor. Sınıfın belirli bir örneğiyle uğraşmadan veya bir örnek nasıl oluşturulacağı ile, SomeClass.instance_method(:a_method) (bağsız bir yöntemdir) yapabilir ve tanımın yerini araştırmak için source_location numaralı telefonu arayın.

Gerçek dünya uygulamalarında bu tür bir metaprogramlama ne zaman gereklidir? Bir örnek, yöntem araması için işlevlere sahip bir IDE oluşturduğunuzdur.