2016-10-24 47 views
6

Mam następujący fragment kodu:instancji zmiennej wewnątrz singleton klasy

class Fish 
# @message = "I can swim" 

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


Fish.action => nil 

Jak tylko odkomentowaniu powyższy @message zmienną Fish.action powraca I can swim. Dlaczego w obu przypadkach ignoruje komunikat I can jump. Dlaczego? Dlaczego klasa Fish jest powiązana z @message zdefiniowaną na początku, ale nie wewnątrz klasy singleton?

+0

To jakże blisko [to pytanie] (http://stackoverflow.com/questions/40211113/how-to-use-hash-inside-instance-eval-ruby) zapytał kilka minut temu. Jeśli przeniesiesz definicję metody klasy 'action' poza klasę singleton i zdefiniuj ją (równoważnie)' def self.action; @wiadomość; Koniec końców, odpowiedzi na wcześniejsze pytanie będą również dotyczyły Twojego pytania. –

Odpowiedz

4

To dlatego class << self otwiera kontekst klasa class Singleton:

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

można zweryfikować przez:

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

Czy możemy powiedzieć "' class << self' zmienia 'self' na' singleton Foo'? Wydaje mi się to bardziej precyzyjne. Wiem, że "otwórz klasę" jest często używana, ale nigdzie (o ile mi wiadomo) Ruby nie zapewnia definicji "otwierania" klasy. –

+0

@CarySwoveland, to oznacza, że ​​tylko 'self' zmienia się, ale obecna klasa również się zmienia (myślę o tym jak' instance_eval' vs 'class_eval'). – ndn

+0

Myślę, że mówimy to samo, że 'self' zmienia się na' Foo.singleton_class' pomiędzy 'class << self' i jego' end'. –