Ruby:动态创建新类

时间:2015-11-01 15:02:39

标签: ruby metaprogramming

我正在尝试动态创建一组类,如下所示。

class Foo
    attr_reader :description
end

['Alpha', 'Beta', 'Gamma'].each do |i|
  klass = Class.new(Foo) do |i|
    def initialize
      @description = i
    end
  end
  Object.const_set(i, klass)
end

而不是手动创建每个类,e。 G:

class Alpha < Foo
  def initialize 
    @description = 'Alpha'
  end
end

执行此类操作的正确方法是什么?如何将迭代器传递给嵌套块?

3 个答案:

答案 0 :(得分:1)

你很亲密。我想你想让description成为一个类实例变量(或者可能是一个类变量),而不是实例变量。对于类description的所有对象,Alpha将为“Alpha”,因此它应该是类的属性。您可以Alpha.description(或Alpha.new.class.description)访问它。这是使用类实例变量的解决方案:

class Foo
  class << self
    attr_reader :description
  end
end

['Alpha', 'Beta', 'Gamma'].each do |i|
  klass = Class.new(Foo)
  klass.instance_variable_set(:@description, i)

  Object.const_set(i, klass)
end

答案 1 :(得分:1)

class Foo
  attr_reader :description
end

['Alpha', 'Beta', 'Gamma'].each do |class_name|
  eval %Q{
    class #{class_name} < Foo
      def initialize
        @description = #{class_name}
      end
    end
    }
end

执行时:

Gamma.new.description
 => Gamma 

答案 2 :(得分:1)

  

如何将迭代器传递给嵌套块?

使用嵌套的。 def不是块。 def会切断def之外的变量的可见性。另一方面,可以看到块外的变量:

class Foo
    attr_reader :description
end

['Alpha', 'Beta', 'Gamma'].each do |class_name|
  klass = Class.new(Foo) do 
    define_method(:initialize) do
      @description = class_name
    end
  end

  Object.const_set(class_name, klass)
end

a = Alpha.new
p a.description

--output:--
"Alpha"

您也可以执行您想要的操作,而无需创建嵌套块或类Foo:

['Alpha', 'Beta', 'Gamma'].each do |class_name|
  klass = Class.new() do
    def initialize
      @description = self.class.name
    end

    attr_reader :description

  end

  Object.const_set(class_name, klass)
end

--output:--
"Alpha"
"Gamma"