2011-08-25 15 views
10

Tworzę dziwną klasę, w której chcę przechwycić każdą metodę wysłaną do obiektu klasy. Mogę osiągnąć większość tego, czego chcę przy użyciu metody method_missing, np.Ruby: Łapanie wszystkich metod wysłanych do obiektu

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

Problem stanowią wszystkie metody instancji, które MyClass dziedziczy po Object. Mógłbym przejrzeć każdą metodę jeden po drugim i przedefiniować je, ale liczyłem na bardziej elastyczne podejście. Wszystkie metody metaprogramowania, które wypróbowałem, skarżyły się z NameError, gdy próbuję dotknąć tych metod instancji.

Odpowiedz

11

Jak zauważył w komentarzach i odpowiedzi z @DanCheail, jeśli używasz ruby ​​1.9+, powinieneś użyć raczej BasicObject niż niezdefiniowanych metod Object. W chwili publikacji tego postu korzystanie z wersji 1.8.x było nadal dość rozpowszechnione, mimo że 1.9 od jakiegoś czasu zostało wydane.


Zamiast próby „przedefiniować” czegokolwiek, można owinąć swój obiekt w wygaszony (w przeważającej części) obiektu proxy, coś jak:

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

Dokładnie tego szukałem! – Max

+0

Znacznie lepiej jest używać BasicObject, ponieważ osiąga to samo i jest o wiele bezpieczniejsze. – Max

+0

Noted. Kiedy ta odpowiedź została opublikowana, 1.8 wciąż było dość powszechne w scenariuszach produkcyjnych, a jako takie "BasicObject" jeszcze nie istniało. – numbers1311407

5

Jeśli używasz Ruby 1.9, można mieć swoje klasy Dziedziczy z BasicObject aby uzyskać czysty łupków do pracy z:

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

+0

Tego rodzaju rzeczy szukam, ale trywialna próba daje mi 'SystemStackError: poziom stosu zbyt głęboki' przy definiowaniu' method_missing'. Hm ... – Max

+2

Co robisz wewnątrz 'method_missing'? Jeśli zrobiłeś coś takiego jak 'puts * args', otrzymasz nieskończoną pętlę' method_missing'. Jeśli potrzebujesz metody 'Kernel', musisz wywołać' :: Kernel.puts', itd. – numbers1311407

1

Jeśli używasz Ruby 1.8 możesz rozważyć użycie klejnotu blankslate.

Powiązane problemy