代码之家  ›  专栏  ›  技术社区  ›  okliv

如何在动态定义类的动态定义子类中动态定义常量

  •  2
  • okliv  · 技术社区  · 6 年前

    我如何在动态定义类的动态定义子类中动态定义一个常量,就像这样,但是没有 NameError: uninitialized constant Foo::Bar 错误:

    Object.const_set('Foo',Class.new) {|klass| klass.const_set('Bar', Class.new){|subklass| subklass.const_set(:YEP,'Yep!')}}
    

    得到:

    > Foo::Bar::YEP #=> 'Yep!'
    
    2 回复  |  直到 6 年前
        1
  •  5
  •   Simple Lime    6 年前

    将方法参数括在圆括号中时,大括号块将应用于方法调用,而不是列表中的最后一个参数。所以那些 { |klass| ... } 正在传递给 Object.const_set 不是为了 Class.new 是的。如果在块后移动右括号,它将起作用,因为块被传递到 类。新建 而不是 对象常量集 以下内容:

    Object.const_set('Foo',Class.new { |klass|
      klass.const_set('Bar', Class.new { |subklass|
        subklass.const_set(:YEP,'Yep!')
      })
    })
    Foo::Bar::YEP # => "Yep!"
    
        2
  •  3
  •   Cary Swoveland    6 年前

    以下相当于@ Simule的回答,只是表达不同而已。

    def make_class(name, parent=Object)
      Object.const_set(name, Class.new(parent))
    end
    
    foo = make_class('Foo')
      #=> Foo
    bar = make_class('Bar', foo)
      #=> Bar
    bar.superclass
      #=> Foo
    bar.const_set('YEP', 'Yep!')
    Bar::YEP
      #=> "Yep!"
    bar::YEP
      #=> "Yep!"
    

    如果需要的话,变量可以被分解出来。

    make_class('Bar', make_class('Foo')).const_set('YEP', 'Yep!')
    Bar::YEP
      # => "Yep!"
    

    Class::new Module#const_set

    动态创建的类通常匿名使用(不命名),在这种情况下,只需编写:

    foo = Class.new
    bar = Class.new(foo)
    bar.const_set('YEP', 'Yep!')
    bar::YEP
      #=> "Yep!"
    

    并通过变量引用类 foo bar .