Ruby class 动态匿名模块中的变量

Ruby class variables in dynamic anonymous module

我正在创建一个匿名模块,因为我需要它是动态的,但是像下面的示例那样使用 class 变量是行不通的。我有这个代码:

class Filter

  def self.mod(var)
    # Creating anonymous module
    m = Module.new do
      def hello
        puts @var
      end

      def self.var=(var)
        @@var = var
      end

      def self.var
        @@var
      end

    end
    # Setting the class variable
    m.var = var
    m
  end
end

f1 = Filter.mod("hello")

puts f1.var # => hello

f2 = Filter.mod("goodbye")

puts f2.var # => goodbye
puts f1.var # => goodbye

为什么我给f2赋值的时候f1变了?我需要每个模块维护自己的变量值。有没有办法用匿名/动态模块来规避这个问题?

如果我在 class 中包含过滤器:

class Main
  include Filter.mod("hello")
end

m = Main.new

puts m.hello # => nil

如何访问@var 变量?

因为您分配给 @@var 这是一个 class 变量。尝试将其更改为 @var.

@@Filter 上定义了一个 class 变量,而不是像您期望的那样在您的新 Module 上定义。您可以通过以下方式查看它:

puts Filter.class_variables.inspect
# [:@@var]

这只存在一次,并且在 Filter.

范围内发生的对 @@var 的每次引用都会被写入

您真正想要的是每个 Module.new 上的 class 实例变量,您只需要一个 @ .这在 Module class.

的新 实例 上定义了 @var
  def self.var=(var)
    @var = var
  end

  def self.var
    @var
  end

# ...

puts f1.class
# Module
puts f1.instance_variables.inspect
# [:@var]

puts f2.var
# goodbye
puts f1.var
# hello