2011-08-25 26 views
10

Sınıfın bir nesnesine gönderilen her yöntemi yakalamak istediğim garip bir sınıf yapıyorum. İstediğim şeyin çoğunu method_missing ile elde edebilirim.Ruby: Nesneye Gönderilen Tüm Yöntemleri Yakalamak

class MyClass 
    def method_missing m, *args 
     # do stuff 
    end 
end 

Sorun, MyClass öğesinin Object'ten miras aldığı örnek yöntemlerin tümüdür. Her bir yöntemi tek tek inceleyip yeniden tanımlayabilirim, ancak daha esnek bir yaklaşım olmasını umuyordum. Çalıştığım metaprogramlama yöntemlerinin tümü, bu örnek yöntemlere dokunmaya çalıştığımda bir NameError ile şikayet etti. , @DanCheail yorumlarına ve cevap belirtildiği gibi

http://ruby-doc.org/core-1.9/classes/BasicObject.html

cevap

11

: Ruby'yi 1.9 kullanıyorsanız

+0

Tam olarak aradığım şey buydu! – Max

+0

Bir BasicObject kullanmak daha iyidir, çünkü aynı şeyi başarır ve çok daha güvenlidir. – Max

+0

Not. Bu cevap yayınlandığında 1.8, üretim senaryolarında hâlâ oldukça yaygındı ve bu nedenle 'BasicObject' henüz mevcut değildi. – numbers1311407

5

, temiz bir barut gelen işe gitmek için BasicObject adresinin sınıf devralma olabilir Ruby 1.9+ kullanıyorsanız, Object undefining yöntemleri yerine BasicObject kullanmalısınız. Bu mesajın yayınlandığı sırada 1,9, bir süredir serbest bırakılmış olsa da hala oldukça yaygındı.


Aksine bir şey "yeniden tanımlama" çalışmak yerine, proxy nesnesi (çoğunlukla için) boşluklu daki nesneyi sarabilirdiniz, gibi bir şey:

class MyProxy 
    instance_methods.each do |meth| 
    # skipping undef of methods that "may cause serious problems" 
    undef_method(meth) if meth !~ /^(__|object_id)/ 
    end 

    def initialize(object) 
    @object = object 
    end  

    def method_missing(*args) 
    # do stuff 
    p args 
    # ... 
    @object.send(*args) 
    end 
end 

MyProxy.new(MyClass.new).whatever 
+0

Bu tür bir şey arıyorum, ama önemsiz bir girişimde, 'method_missing' tanımlanırken bana bir 'SystemStackError: stack level 'fazla derinlik verir. Hm ... – Max

+2

'method_missing' içinde ne yapıyorsunuz? Eğer 'args' gibi bir şey yaptıysan sonsuz bir 'method_missing 'döngüsü elde edeceksin. Eğer bir 'Kernel' yöntemine ihtiyacınız varsa, ':: Kernel.puts', vb. 'Yi çağırmanız gerekir. – numbers1311407

1

Ruby'nin 1.8 kullanıyorsanız boşluk taşını kullanmayı düşünebilirsiniz.

İlgili konular