通过字符串在模块中创建类的实例

时间:2011-05-23 19:52:13

标签: ruby

说我在test.rb中有这个Ruby代码

module MyModule
  class TestClassA
  end

  class TestClassB
    def initialize
      a = Object.const_get('MyModule::TestClassA').new
    end
  end
end

这里的ruby shell中的一些测试以irb -r test.rb开始:

ruby-1.8.7-p302 > MyModule
 => MyModule 
ruby-1.8.7-p302 > MyModule::TestClassA
 => MyModule::TestClassA 
ruby-1.8.7-p302 > MyModule::TestClassA.new
 => #<MyModule::TestClassA:0x10036bef0> 
ruby-1.8.7-p302 > MyModule::TestClassB
 => MyModule::TestClassB 
ruby-1.8.7-p302 > MyModule::TestClassB.new
NameError: wrong constant name MyModule::TestClassA
    from ./test.rb:7:in `const_get'
    from ./test.rb:7:in `initialize'
    from (irb):1:in `new'
    from (irb):1

为什么Object.const_get('MyModule::TestClassA').new的构造函数中的TestClassB会失败而MyModule::TestClassA.new在控制台中有效? 我也试过Object.const_get('TestClassA').new,但这也不起作用。

3 个答案:

答案 0 :(得分:17)

没有名为“MyModule :: TestClassA”的常量,在名为MyModule的常量中有一个名为TestClassA的常量。

尝试:

module MyModule
  class TestClassA
  end

  class TestClassB
    def initialize
      a = Object.const_get("MyModule").const_get("TestClassA").new
    end
  end
end

至于为什么它不起作用,这是因为::是一个运算符而不是命名约定。

http://www.ruby-forum.com/topic/182803

提供了其他示例和信息

答案 1 :(得分:0)

在Ruby 2.0+中,这很好用:

#! /usr/bin/env ruby

module Foo
  class Bar
    def initialize(baz)
      @baz = baz
    end

    def qux
      puts "quux: #{@baz}"
    end
  end
end

Kernel.const_get("Foo::Bar").new('corge').qux

结果:

bash-3.2$ ./test.rb
quux: corge

答案 2 :(得分:0)

我认为你可以使用Object.const_get

klass = Object.const_get "ClassName"
klass.new