在类中动态创建静态变量

时间:2015-02-10 13:53:14

标签: ruby

我有以下课程:

class A
  X = %w(a b c)
end

如何使用A中的值为类X创建静态变量列表,以便最终得到与以下内容相同的内容:

class A
  a = 1
  b = 2
  c = 3
end

我发现可以使用define_method定义方法,但我不太了解如何为变量执行此操作。

3 个答案:

答案 0 :(得分:4)

不幸的是,你想要的是AFAIK是不可能的。您根本无法动态地将局部变量引入范围。你可能想做这样的事情:

class A
  X = %w(a b c)
end

class A
  bnd = binding

  X.each.with_index(1) do |var, i|
    bnd.local_variable_set(var, i)
  end
end

但那不会奏效。当您使用local_variable_set创建 new 变量时,该变量将仅存在于Binding对象中,而不在Binding创建的范围内。

class A
  bnd = binding

  X.each.with_index(1) do |var, i|
    eval("#{var} = #{i}", bnd)
  end
end

这也不会奏效。实际上,它只是等同于第一个。

好的,所以你想:"让我们不要使用Binding,然后,只是简单地eval":

class A
  X.each.with_index(1) do |var, i|
    eval("#{var} = #{i}")
  end
end

不,这也不起作用。局部变量仍然仅在eval内创建,但它们不会泄露到外面。 (他们在1.8岁及以上的时候发生泄漏,但他们已经不再在1.9+了。)事实上,即使他们确实被创建了,他们也会在块的范围内创建。因此,您必须使用for / in代替。

另请注意,即使 if 您设法将局部变量注入范围,它们仍然是局部变量:您无法从其他任何位置访问它们。 (除非你以某种方式设法抓住Binding并致电local_variable_get。)

使 更有意义制作方法,这更容易:

class A
  X.each.with_index(1) do |var, i|
    define_singleton_method(:var) do i end
  end
end

现在,也可以从范围之外访问它们:

A.a # => 1

或使用有点模糊的方法使用范围解析运算符调用语法:

A::a # => 1

当然,因为它们总是返回相同的值,为什么不将它们设为常量?

class A
  X.each.with_index(1) do |var, i|
    const_set(var.upcase, i)
  end
end

答案 1 :(得分:3)

常量定义如下(它们必须以大写字母开头):

class A
  A = 1
  B = 2
  C = 3
end

A::A #=> 1
A::B #=> 2
A::C #=> 3

要动态定义它们,请使用const_set

class A
  %w(A B C).each.with_index(1) { |c, i| const_set(c, i) }
end

答案 2 :(得分:1)

有一些元编程疯狂,你可以做类似

的事情
  class A
    class << self
      def A.X(args)
        puts "Creating methods"
        args.each do |arg|
          define_singleton_method(arg) {
            if class_variable_defined? "@@#{arg}"
              class_variable_get("@@#{arg}")
            else
             nil
            end
          }
          define_singleton_method("#{arg}=") { |val|
            class_variable_set("@@#{arg}", val)
          }
        end
      end
    end
  end

允许你这样做

  class A
    X %w(a b c)
    A.a = 1
    A.b = 2
    A.c = 3
  end

需要使用A.a,A.b等前缀,因为有一些ruby语法的东西

相关问题