我如何在动态定义的类的动态定义的子类中动态定义一个常量,就像这样,但是没有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!'
答案 0 :(得分:5)
将方法参数括在括号中时,花括号块将应用于方法调用,而不是列表中的最后一个参数。因此,那些{ |klass| ... }
被传递给Object.const_set
而不是Class.new
。如果您将封闭括号移到块后,它将起作用,因为块将传递给Class.new
而不是Object.const_set
:
Object.const_set('Foo',Class.new { |klass|
klass.const_set('Bar', Class.new { |subklass|
subklass.const_set(:YEP,'Yep!')
})
})
Foo::Bar::YEP # => "Yep!"
答案 1 :(得分:3)
以下等同于@SimpleLime的答案,只是表达方式有所不同。
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
引用类。