2010-08-15 21 views
18
class C 
end 

var = "I am a local var outside" 

C.class_eval do 
    def self.a_class_method 
    puts var 
    end 
end 

Je sais, ce n'est pas correct, car le def a créé une nouvelle portée. Je sais aussi que l'utilisation define_method peut créer une méthode d'instance sans créer une nouvelle portée, mais mon point est de savoir comment définir une méthode de classe .Comment définir dynamiquement une méthode de classe qui fera référence à une variable locale à l'extérieur?

Répondre

44

Les méthodes de classe n'existent pas réellement dans Ruby, elles ne sont que des méthodes singleton de l'objet de classe. Les méthodes singleton n'existent pas vraiment, elles ne sont que des méthodes d'instance ordinaires de la classe singleton de l'objet.

Puisque vous savez déjà comment définir des méthodes d'instance (en utilisant Module#define_method), vous savez déjà tout ce que vous devez savoir. Vous avez juste besoin d'appeler class_eval sur la classe singleton de C au lieu de C lui-même:

(class << C; self end).class_eval do 
    define_method(:a_class_method) do 
    puts var 
    end 
end 

Les versions actuelles de Ruby ont une méthode singleton_class pour rendre cela plus facile: les versions

C.singleton_class.class_eval do 
    define_method(:a_class_method) do 
    puts var 
    end 
end 

Mais en fait, en cours de Ruby a également Module#define_singleton_method, donc, dans ce cas particulier, c'est inutile:

C.define_singleton_method(:a_class_method) do 
    puts var 
end 
+0

Merci beaucoup! – Croplio

+0

Bonne réponse. Pourriez-vous partager des liens vers la documentation de ruby ​​sur la méta-programmation des méthodes de classe? merci – mattgathu

+0

@mattgathu: Il n'y a pas de méthodes de classe dans Ruby. Il n'y a qu'un seul type de méthodes: les méthodes d'instance. –

0

vous pouvez le faire simplement de cette façon

class << C 
    define_method(:a_class_method) do 
    # do something 
    end 
end