2016-10-24 1 views
6

J'ai le morceau de code suivant:Variable d'instance dans la classe singleton

class Fish 
# @message = "I can swim" 

class << self 
    @message = "I can jump!" 
    define_method(:action) { @message } 
end 
end 


Fish.action => nil 

Dès que je décommenter la variable @message ci-dessus, Fish.action rendements I can swim. Pourquoi dans les deux cas, il ignore le message I can jump. Pourquoi donc? Pourquoi la classe Fish est-elle liée au @message défini au début mais pas à la classe singleton?

+0

Ceci est oh-so-près de [cette question] (http://stackoverflow.com/questions/40211113/how-to-use-hash-inside-instance-eval-ruby) vient de poser la question il y a quelques minutes. Si vous déplacez la définition de la méthode de classe 'action' en dehors de la classe singleton et la définissez (de manière équivalente)' def self.action; @message; fin », les réponses à la question précédente s'appliqueraient également à votre question. –

Répondre

4

C'est parce que class << self ouvre le contexte de la classe singleton classe: Vous pouvez vérifier que par

class Foo 
    p self # Foo 
    class << self 
    p self # #<Class:Foo> 
    define_method(:bar) { p self } # Foo 
    end 
end 
Foo.bar 

:

Fish.singleton_class.instance_variable_get(:@action) # => "I can jump!" 
+0

Pouvons-nous dire "' 'classe << self' change' self' en '' singoo class '' de Foo' "? Cela me semble plus précis. Je sais que "ouvrir une classe" est souvent utilisé, mais nulle part (pour autant que je sache) Ruby ne donne une définition pour "ouvrir" une classe. –

+0

@CarySwoveland, cela implique que seul 'self' change, mais la classe actuelle change aussi (pensez à' instance_eval' vs 'class_eval'). – ndn

+0

Je pense que nous disons la même chose, que 'self' est changé en' Foo.singleton_class' entre 'class << self' et son' end'. –