Совместное использование переменных класса между экземпляром и самим классом при расширении внутри модуля - PullRequest
3 голосов
/ 18 сентября 2010

Я пытаюсь понять, почему этот код:

class BaseClass
end

module Extensions
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def message(message)
      @@message = message
    end
  end
end

BaseClass.send(:include, Extensions)

class ExtendedClass < BaseClass
  message "hello world!"

  def say_message
    puts @@message
  end
end

ExtendedClass.new.say_message

выводит:

test.rb:22:in `say_message': uninitialized class variable @@message in ExtendedClass (NameError)
    from test.rb:26:in `<main>'

вместо

hello world!

Не могли бы вы объяснить, почему

1 Ответ

2 голосов
/ 19 сентября 2010

Потому что, когда этот метод выполняется:

def message(message)
  @@message = message
end

@@ message относится к переменной класса в модуле ClassMethods (не в классе ExtendedClass)

Вот одно строчное изменение, которое заставляет его работать так, как вы ожидаете:

def message(message)
  self.send(:class_variable_set, "@@message", message)
end

Это немного антипаттерн (использование 'send', чтобы обойти тот факт, что 'class_variable_set' является приватным), но я верю, что это отвечает на вопрос.

НТН

...