2016-10-24 3 views
6

У меня есть следующий фрагмент кода:переменная экземпляра внутри класса одноплодной

class Fish 
# @message = "I can swim" 

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


Fish.action => nil 

Как только я раскомментируйте выше @message переменной, Fish.action возвращает I can swim. Почему в обоих случаях он игнорирует сообщение I can jump. Почему это? Почему класс Fish привязан к @message, определенному в начале, но не внутри класса singleton?

+0

Это о так близко к [этот вопрос] (HTTP://stackoverflow.com/questions/40211113/how-to-use-hash-inside-instance-eval-ruby) попросил несколько минут назад. Если вы переместите определение метода класса 'action' вне класса singleton и определите его (эквивалентно)' def self.action; @сообщение; end', ответы на более ранний вопрос будут применены и к вашему вопросу. –

ответ

4

Это потому, что class << self открывает контекст класса синглтон класс:

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

Можем ли мы сказать, что '' class << self' изменяет 'self' на« одноэлементный класс Foo »? Мне кажется более точным. Я знаю, что «открывать класс» часто используется, но нигде (насколько я знаю) Ruby предоставляет определение для «открытия» класса. –

+0

@CarySwoveland, это означает, что изменяется только «self», но текущий класс также изменяется (подумайте об этом как 'instance_eval' vs' class_eval'). – ndn

+0

Я думаю, что мы говорим то же самое, что 'self' изменяется на' Foo.singleton_class' между 'class << self' и его' end'. –

Смежные вопросы