繁体   English   中英

如何选择要在Ruby中动态包含的模块版本?

[英]How can I choose which version of a module to include dynamically in Ruby?

我正在编写一个小的Ruby命令行应用程序,该应用程序使用标准库中的fileutils进行文件操作。 根据用户调用应用程序的方式,我将希望包含FileUtilsFileUtils::DryRunFileUtils::Verbose

由于include是私有的,因此,我无法将逻辑选择纳入对象的initialize方法中。 (这是我的第一个想法,从那时起,我可以将有关用户选择的信息作为参数传递给new 。)我提出了两个似乎可行的选项,但我都不满意:

  1. 根据用户的选择在应用程序的名称空间中设置全局变量,然后在类中进行条件包含:

     class Worker case App::OPTION when "dry-run" include FileUtils::DryRun etc. 
  2. 创建子类,唯一的区别是它们包括哪个FileUtils版本。 根据用户的选择,选择适当的一种。

     class Worker include FileUtils # shared Worker methods go here end class Worker::DryRun < Worker include FileUtils::DryRun end class Worker::Verbose < Worker include FileUtils::Verbose end 

第一种方法似乎是DRY-er,但我希望有一些我没想到的更简单的方法。

那如果是私人的呢?

class Worker
  def initialize(verbose=false)
    if verbose
      (class <<self; include FileUtils::Verbose; end)
    else
      (class <<self; include FileUtils; end)
    end
    touch "test"
  end
end

这包括FileUtils::something特别是Worker的元类-不在主Worker类中。 不同的工作人员可以通过这种方式使用不同的FileUtils

如果您想避免“切换”并注入模块,则

def initialize(injected_module)
    class << self
        include injected_module
    end
end

语法不起作用(injected_module变量超出范围)。 您可以使用self.class.send技巧,但是每个对象实例扩展对我来说似乎更合理,不仅因为编写起来更短:

def initialize(injected_module = MyDefaultModule)
    extend injected_module
end

但同时也最大程度地减少了副作用-类的共享状态和易于更改的状态,这可能导致大型项目出现意外行为。 可以这么说,在Ruby中并不是真正的“隐私”,但是有些方法被标记为私有不是没有原因的。

通过以下测试示例,有条件地通过send方法有条件地包括模块对我来说是有效的:

class Artefact
  include HPALMGenericApi
  # the initializer just sets the server name we will be using ans also the 'transport' method : Rest or OTA (set in the opt parameter)
  def initialize server, opt = {}  
    # conditionally include the Rest or OTA module
    self.class.send(:include, HPALMApiRest) if (opt.empty? || (opt && opt[:using] opt[:using] == :Rest)) 
    self.class.send(:include, HPALMApiOTA) if (opt && opt[:using] opt[:using] == :OTA)    
    # ... rest of initialization code  
  end
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM