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)

注: プライベート メソッドはプライベートのままにする必要があります。

ユースケースは次のとおりです。さまざまなスコアリング手法を含むいくつかのモジュールが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

ユースケースが提供されていない前の例:

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)

publicさらに、 、private、 などのアクセシビリティ キーワードの順序にも注意する必要がありますmodule_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#pooperprivatemodule_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 に答える