从Ruby中的模块函数访问私有方法

时间:2013-08-29 18:34:44

标签: ruby module

我正在尝试为模块功能创建私有帮助器方法无济于事。我觉得我有一些非常简单的东西。

使用更易理解的用例更新示例:

module FancyScorer
  module_function

  def score(ary)
    scores = []
    ary.each_slice(2).with_index do |slice, i|
      scores <<
        case i % 2
        when 0
          score_eventh(ary)
        else
          score_oddth(ary)
        end
    end
    scores.inject(:+)
  end

  private

  def score_eventh(ary)
    ary.inject(:+) / (ary.size - 1)
  end

  def score_oddth(ary)
    ary.inject(:*) / (ary.size - 1)
  end
end

FancyScorer.score([1,2,3,4])
# => `block in score_curiously': undefined method `score_eventh'
#    for FancyScorer:Module (NoMethodError)

注意:私有方法应保密。

以下是用例:有几个模块包含各种评分技术,例如: FancyScorerSimpleScorerComplexScorer。这些函数是独立测试的,然后用于为不同的类创建score方法。例如:

class A
  ...
  def score    
    FancyScorer.score(metrics) + 2*SimpleScorer.score(metrics)
  end
end

class B
  ...
  def score
    0.5*FancyScorer.score(metrics) + 2*SimpleScorer.score(metrics[0,3]) + ComplexScorer.score(metrics)
  end
end

上一个没有提供用例的示例:

module Party
  module_function

  def pooper
    enjoy
  end

  private

  def enjoy
    puts "Wahoo!"
  end
end

Party.pooper
# => NameError: undefined local variable or method `enjoy' for Party:module
#            from (party): in `pooper`

1 个答案:

答案 0 :(得分:10)

module_function(symbol, ...) → self说: -

  

为命名方法创建模块函数。 可以使用模块作为接收器来调用这些函数, ,并且这些函数也可以作为混合在模块中的类的实例方法。模块功能是原件的副本,因此可以单独更改。实例方法版本是私有的。如果不带参数使用,则随后定义的方法将成为模块函数。

您需要确保将辅助方法声明为#private_class_methodprivate仅影响实例方法。

module Party

  def enjoy
    puts 'hello'
  end

  def pooper
    enjoy
  end

  private_class_method :enjoy
  module_function :pooper
end

Party.pooper # => 'hello'
Party.enjoy # => private method `enjoy' called for Party:Module (NoMethodError)

此外,您应该注意publicprivatemodule_function等辅助功能关键字的排序。 这些不重叠,而是覆盖。

module Party
  module_function # Module function declarations begin
  def pooper
    bar
  end
  def bar
    enjoy
  end

  private         # Private declarations begin, module function declarations end
  module_function # Private declarations end, module function declarations begin
  def enjoy       # Therefore, this is a module function
    "Wahoo!"
  end
end

Party.pooper # => "Wahoo!"
Party.bar # => "Wahoo!"
Party.enjoy # => "Wahoo!"  <-- No longer private

请注意,module_function会覆盖之前的private声明。


以下是module_function完成工作时的更多示例,以及何时没有。

一旦弹出另一个辅助功能关键字,module_function定义就会停止。在此示例中,module_functionpublic中断,使#pooper成为公共实例方法。使用private同样会阻止module_method

module Party
  module_function
  public
  def pooper
    "i am pooper"
  end
end

Party.pooper
# undefined method `pooper' for Party:Module (NoMethodError)

现在,如果订单已更改:

module Party
  public
  module_function
  def pooper
    "i am pooper"
  end
end

Party.pooper # => "i am pooper"