代码之家  ›  专栏  ›  技术社区  ›  TheNovice

跨两个Ruby模块继承/共享代码

  •  2
  • TheNovice  · 技术社区  · 7 年前

    我是Noob,正在找人帮忙把这个弄干。假设我有 module DoAThing 看起来是这样的:

    module DoAThing
      class ExportNames
        def initialize(names, limit = 1000)
          @names = names
          @limit = limit
        end
    
        def perform
          awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
          awesome.generate_export(::ClassAwesome::EXPORT_DEFAULTS)
        end
      end
    end
    

    然后我想添加一个模块,该模块的功能完全相同,只是在生成报告时,我想传递一个不同的常量,如下所示:

    module DoASlightDifferentThing
      class ExportNames
        def initialize(names, limit = 1000)
          @names = names
          @limit = limit
        end
    
        def perform
          awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
          awesome.generate_export(::ClassAwesome::DIFFERENT_EXPORT_DEFAULTS)
        end
      end
    end
    

    我怎样才能优雅地擦干这个?实际上,我所需要做的就是传入一个不同的常量,即我想交换 EXPORT_DEFAULTS 对于 DIFFERENT_EXPORT_DEFAULTS

    3 回复  |  直到 7 年前
        1
  •  4
  •   Aleksei Matiushkin    7 年前

    这通常被称为依赖注入,互联网上有很多关于这个主题的文章。主要方法是在调用中接受一个参数 #perform 方法:

    module DoManyDifferentThings
      class ExportNames
        def initialize(names, limit = 1000)
          @names = names
          @limit = limit
        end
    
        def perform(report)
          awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
          awesome.generate_export(report)
        end
      end
    end
    

    可以这样称呼:

    DoManyDifferentThings::ExportNames.perform(
      ::ClassAwesome::EXPORT_DEFAULTS
    )
    

    无论report方法是否应该具有预定义的签名,都可以使用类继承:

    module DoManyDifferentThings
      class ExportNames
        def initialize(names, limit = 1000)
          @names = names
          @limit = limit
        end
    
        def perform
          awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
          awesome.generate_export(self.class.constant_get('REPORT'))
        end
      end
    
      class ExportNames1 < ExportNames
        REPORT = ::ClassAwesome::EXPORT_DEFAULTS_1
      end
    
      class ExportNames1 < ExportNames
        REPORT = ::ClassAwesome::EXPORT_DEFAULTS_2
      end
    end
    

    或者,也可以声明要在子体中覆盖的方法:

    module DoManyDifferentThings
      class ExportNames
        def initialize(names, limit = 1000)
          @names = names
          @limit = limit
        end
    
        def perform
          awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
          awesome.generate_export(report)
        end
    
        protected
    
        def report
          raise "DO NOT CALL ME DIRECTLY"
        end
      end
    
      class ExportNames1 < ExportNames
        def report
          ::ClassAwesome::EXPORT_DEFAULTS_1
        end
      end
    
      class ExportNames2 < ExportNames
        def report
          ::ClassAwesome::EXPORT_DEFAULTS_2
        end
      end
    end
    
        2
  •  2
  •   Alexis    7 年前

    可以将此常量作为参数移动,也可以使用ihneritance。

    提供默认值作为参数

    module DoAThing
      class ExportNames
        def initialize(names, limit = 1000, defaults = ::ClassAwesome::EXPORT_DEFAULTS)
          @names = names
          @limit = limit
          @defaults = defaults
        end
    
        def perform
          awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
          awesome.generate_export(@defaults)
        end
      end
    end
    

    您可以执行以下操作,而不是调用DoaSlingDifferentThing::ExportNames:

    DoAThing::ExportNames.perform_now(names, 1000, ::ClassAwesome::DIFFERENT_EXPORT_DEFAULTS)
    

    Ihneritance公司

    或者,您可以使用ihneritance,其中我们添加了一个将被覆盖的默认方法:

    module DoAThing
      class ExportNames
        def initialize(names, limit = 1000)
          @names = names
          @limit = limit
        end
    
        def perform
          awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
          awesome.generate_export(defaults)
        end
    
        def defaults
          ::ClassAwesome::EXPORT_DEFAULTS
        end
      end
    end
    
    module DoASlightDifferentThing
      class ExportNames < DoAThing::ExportNames
        def defaults
          ::ClassAwesome::DIFFERENT_EXPORT_DEFAULTS
        end
      end
    end
    
        3
  •  0
  •   Nimish Gupta    7 年前

    如果这两个类的名称空间可以相同,那么我将通过如下方式重写代码来清理代码

    module DoAThing
      class ExportNames
        def initialize(names, limit = 1000)
          @names = names
          @limit = limit
        end
    
        def perform(value)
          awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
          awesome.generate_export(value)
        end
      end
    end 
    

    现在我要打电话

    DoAThing::ExportNames.new('your names').perform(::ClassAwesome::EXPORT_DEFAULTS)
    DoAThing::ExportNames.new('your names').perform(::ClassAwesome::DIFFERENT_EXPORT_DEFAULTS)