2010-07-04 26 views
1

J'ai un Mix-in qui reflète sur la classe de récepteur pour générer du code. Cela signifie que je dois exécuter la méthode de classe à la fin de la définition de classe, comme dans ce trivialement abêtis exemple:Exécution d'une méthode mixin à la fin d'une définition de classe

module PrintMethods 
    module ClassMethods 
    def print_methods 
     puts instance_methods 
    end 
    end 

    def self.included(receiver) 
    receiver.extend ClassMethods 
    end 
end 

class Tester 
    include PrintMethods 

    def method_that_needs_to_print 
    end 

    print_methods 
end 

Je voudrais avoir le mixin faire cela pour moi automatiquement, mais je peux ne viens pas avec un moyen. Ma première pensée était d'ajouter receiver.print_methods à self.included dans le mixin, mais cela ne fonctionnera pas parce que la méthode que je veux refléter n'a pas encore été déclarée. Je pourrais appeler include PrintMethods à la fin de la classe, mais cela ressemble à une mauvaise forme.

Existe-t-il des astuces pour que cela se produise, donc je n'ai pas besoin d'appeler print_methods à la fin de la définition de la classe?

Répondre

2

Tout d'abord, il n'y a pas de fin de définition de classe. Rappelez-vous que dans Ruby vous pouvez rouvrir la méthode de la classe Tester après l'avoir 'initialisée', ainsi l'interpréteur ne peut pas savoir où la classe 'se termine'.

La solution que je peux trouver est de faire la classe via une méthode d'aide, comme

module PrintMethods 
    module ClassMethods 
    def print_methods 
     puts instance_methods 
    end 
    end 

    def self.included(receiver) 
    receiver.extend ClassMethods 
    end 
end 

class Object 
    def create_class_and_print(&block) 
    klass = Class.new(&block) 
    klass.send :include, PrintMethods 
    klass.print_methods 
    klass 
    end 
end 

Tester = create_class_and_print do 
    def method_that_needs_to_print 
    end 
end 

Mais certainement avoir à définir des classes de cette façon fait mal aux yeux.

+0

Ouch. Oui, ça fait mal. Il a aussi print_methods chaque fois qu'une instance est créée. En fin de compte, il suffit de le faire une fois ou lorsque la classe est modifiée. D'ailleurs, je pourrais juste ajouter une méthode d'initialisation d'instance sur la classe ... Je pense que je vais juste devoir appeler la méthode à la fin de la classe. –

+0

'print_methods' n'est pas appelé lorsque vous créez une instance de Tester, juste lorsque vous créez la classe. Oh, et d'ailleurs, je ne sais pas pourquoi j'ai défini create_class_and_print dans la classe Object en premier lieu, vous auriez pu le définir dans un module, ou ailleurs en dehors de Object. – Chubas

+0

OK, je comprends. Oui, je pense que c'est probablement sur la meilleure façon de faire ce que je veux faire ... mais je vais probablement juste exiger qu'il soit appelé et être fait avec. Merci. –