使用可转发指定类

时间:2015-05-27 12:19:12

标签: ruby delegation

我正在尝试使用ruby的forwardable module来使一个类中的某些变量可以被另一个类访问。但是我在做这件事时遇到了一些麻烦。

似乎我能够'转发'self中的一些变量(代码的第一位),但是我无法在类中转发某些变量(第二位代码)

以下作品:

require 'forwardable'
module ModuleName
  #
  class << self
    attr_accessor :config
    def run
      @config = {hey: 'hi', jay: 'ji'}
      puts "1) Config = #{config}"
    end
  end

  #
  class Start
    extend Forwardable
    def_delegators ModuleName, :config
    def run
      puts "2) Config = #{config}"
    end
  end
end


ModuleName.run
(ModuleName::Start.new).run

#=> 1) Config = {:hey=>"hi", :jay=>"ji"}
#=> 2) Config = {:hey=>"hi", :jay=>"ji"}

但这不是

require 'forwardable'
module ModuleName
  #
  class Data
    attr_accessor :config
    def run
      @config = {hey: 'hi', jay: 'ji'}
      puts "1) Config = #{config}"
    end
  end

  #
  class Start
    extend Forwardable
    def_delegators ModuleName::Data, :config
    def run
      puts "2) Config = #{config}"
    end
  end
end


(ModuleName::Data.new).run
(ModuleName::Start.new).run

#=> 1) Config = {:hey=>"hi", :jay=>"ji"}
#=> /Users/ismailm/Desktop/ex.rb:17:in `run': undefined method `config' for ModuleName::Data:Class (NoMethodError)

你能帮忙解决这部分代码......

1 个答案:

答案 0 :(得分:2)

通常,当您在两个类之间委派时,一个对象包含另一个对象的实例。你调用(ModuleName::Data.new).run这个事实对我意味着你正在尝试做的事情,但是在某种程度上错过了你需要将某个包含的类的实例存储在某个地方以便接收对{{{ 1}}

您的第二段代码的这种变化更接近我在委托方案中看到的内容:

:config

我将构造函数更改为require 'forwardable' module ModuleName # class Data attr_accessor :config def initialize @config = {hey: 'hi', jay: 'ji'} end def run puts "1) Config = #{config}" end end # class Start extend Forwardable def initialize data_obj = Data.new() @data = data_obj end def_delegators :@data, :config def run puts "2) Config = #{config}" end end end (ModuleName::Data.new).run (ModuleName::Start.new).run 以显示常用模式,此处未使用。也就是说,您经常传入包装对象,或者更常见的是允许您构造新对象并将其分配给您希望委派给的实例变量的参数。

次要相关更改:在原始代码中,ModuleName::Start的值仅通过调用@config设置,因此直接委派给:run不会读取您的值期待在测试中。它在第一个版本中工作,因为:config在模块的第一次调用@config中设置,然后在第二次委托调用时全局读取为单例方法。我通过在run的构造函数中设置它来解决这个问题,当然,任何在你委托的实例上设置Data值的东西都可以工作。