Ruby中有多个同名的类

时间:2014-02-11 18:24:38

标签: ruby namespaces

我有一个单元测试的现有代码库,其中为每个测试定义了相同的类,以及一个迭代它们的程序。像这样:

test_files.each do |tf|   
  load "tests/#{tf}/"+tf
  test=     ::Kernel.const_get("my_class")
  Test::Unit::UI::Console::TestRunner.run( test )

在进行这些测试时,我意识到ruby允许你从不同的文件中使用相同名称的require类,并且它合并了两者的方法。一旦类层次结构不相同,这就会导致问题:superclass mismatch for class ...

不幸的是,仅仅unloading the class是不够的,因为层次结构中还有许多其他类仍在加载。

有没有办法在不同的全局命名空间中执行每个测试?

虽然我认为使用模块是可行的方法,但我并不满足于手动更改数百个现有文件的想法。

- 编辑 -

根据Cary Swoveland的建议,我已将测试运行代码移至单独的.rb文件,并使用反引号运行它。虽然这看起来效果很好,但是加载ruby解释器并再次require所有库会产生相当大的开销。此外,跨平台兼容性还需要一些额外的工作。

1 个答案:

答案 0 :(得分:2)

首先,我想提出以下解决方案:

#main.rb
modules = []

Dir.foreach('include') do |file|
  if file =~ /\w/
    new_module = Module.new

    load "include/#{file}"

    new_module.const_set("StandardClass", StandardClass)

    Object.send(:remove_const, :StandardClass)

    modules << new_module
  end

end

modules.each do |my_module|
  my_module::StandardClass.standard_method
end

#include/first.rb
class StandardClass
  def self.standard_method
    puts "first method"
  end
end

#include/second.rb
class StandardClass
  def self.standard_method
    puts "second method"
  end
end

这用自己的模块包装每个类,并在其模块中调用类:

$ruby main.rb
second method
first method

但是当你回答时,有对其他类的引用,所以模块可以打破它们。 我通过调用其中一个包装类中的第三个类来检查这个并获得:

include/second.rb:5:in `standard_method': uninitialized constant StandardClass::Independent (NameError)

所以使用反引号可能是更好的解决方案,但我希望我的回答对其他类似情况有帮助。