6

我正在尝试为模块函数创建私有辅助方法,但无济于事。我觉得我缺少一些非常简单的东西。

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

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`
4

1 回答 1

10

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

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

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

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_function通过创建公共实例方法来public中断#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"
于 2013-08-29T18:51:13.250 回答