2011-08-25 50 views
10

我正在製作一個奇怪的類,我想捕獲發送到類的對象的每個方法。我可以通過method_missing實現我想要的大部分內容,例如Ruby:捕獲發送到對象的所有方法

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

問題在於MyClass從Object繼承的所有實例方法。我可以一一瀏覽每種方法並重新定義它們,但我希望採取更靈活的方法。當我嘗試觸摸這些實例方法時,我嘗試過的所有元編程方法都有一個NameError抱怨。

回答

11

誠如@DanCheail的評論和答覆指出,如果您使用的是Ruby 1.9或更高版本,則應使用BasicObject而不是未定義的方法Object。在本貼發佈時,儘管1.9版已經發布了一段時間,1.8.x的使用仍然非常普遍。


,而不是試圖「重新定義」什麼,你可以換你的對象在衝裁(大部分)代理對象,像:

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

這就是我正在尋找的! – Max

+0

使用BasicObject會好得多,因爲它完成同樣的事情並且更安全。 – Max

+0

已記錄。當發佈這個答案時,1.8在生產場景中仍然很常見,因此'BasicObject'還不存在。 – numbers1311407

5

如果您使用Ruby 1.9的,你可以有你的類繼承BasicObject得到一個乾淨的石板從工作:

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

+0

這就是我正在尋找的東西,但是當定義'method_missing'時,一個微不足道的嘗試給了我一個'SystemStackError:堆棧層次太深'。嗯...... – Max

+2

你在做什麼'method_missing'?如果你做了'puts * args'之類的東西,你將得到一個無限的'method_missing'循環。如果你需要一個'Kernel'方法,你必須調用':: Kernel.puts'等。 – numbers1311407

1

如果你使用Ruby 1.8你可以考慮使用blankslate寶石。

相關問題