ruby - Ruby 中的多个同名类

标签 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​​ 解释器并再次要求所有库会产生相当大的开销。此外,跨平台兼容性需要一些额外的工作。

最佳答案

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

#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)

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

关于ruby - Ruby 中的多个同名类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21710017/

相关文章:

C++:在程序逻辑/条件命名空间中使用命名空间?

c# - 错误 : The type or name space "GraphQLRequest" could not be found

c++ - 在命名空间 C++ 中隐藏变量

C++ 使用命名空间来避免长路径

ruby - Minitest 断言在检查时失败

ruby-on-rails - #<#<Class :0x0 的未定义方法 'pathname'

mysql - 针对数百万阵列 IDS 优化 Rails IN 查询

ruby - 从Ruby中的子类方法调用父类中的方法

ruby - 如何使用puppet在服务器上设置环境变量?

c++ - 使用 foo::bar 不会屏蔽 typedef-name::bar?