在模块中扩展时,在实例和类本身之间共享类变量

时间:2010-09-18 16:44:38

标签: ruby class variables module metaprogramming

我正在试图解释为什么这段代码:

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 个答案:

答案 0 :(得分:2)

因为执行此方法时:

def message(message)
  @@message = message
end

@@ message引用模块ClassMethods中的类变量(不是类ExtendedClass)

这是一个单行更改,使其按预期方式工作:

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

这是一个反模式(使用'send'来绕过'class_variable_set'是私有的这一事实),但我相信它回答了这个问题。

HTH