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

fny*_*fny 6 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)
Run Code Online (Sandbox Code Playgroud)

注意:私有方法应保持私有.

这里的使用情况:有一些含有各种评分技术的几个模块,例如FancyScorer,SimpleScorer,ComplexScorer.这些函数是独立测试的,然后用于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
Run Code Online (Sandbox Code Playgroud)

以前没有提供用例的示例:

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`
Run Code Online (Sandbox Code Playgroud)

Aru*_*hit 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)
Run Code Online (Sandbox Code Playgroud)

此外,你应该小心无障碍关键字像的顺序public,privatemodule_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
Run Code Online (Sandbox Code Playgroud)

请注意这里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)
Run Code Online (Sandbox Code Playgroud)

现在,如果订单被更改:

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

Party.pooper # => "i am pooper"
Run Code Online (Sandbox Code Playgroud)