質問

2部構成の質問があります

ベストプラクティス

  • パブリックインターフェイスを使用してデータ構造に何らかの操作を実行するアルゴリズムがあります
  • 現在、多数の静的メソッドを備えたモジュールであり、1つのパブリックインターフェイスメソッドを除き、すべてプライベートです。
  • すべてのメソッドで共有する必要があるインスタンス変数が1つあります。

これらは私が見ることができるオプションで、どれが最良ですか?

  • モジュール静的(Rubyでは「モジュール」)メソッド
  • クラスと静的メソッド
  • データ構造に含めるための
  • Mixin モジュール
  • リファクタリングそのデータ構造を変更するアルゴリズムの部分(非常に小さい)を取り除き、アルゴリズムモジュールの静的メソッドを呼び出すmixinを作成します

技術部分

プライベートモジュールメソッドを作成する方法はありますか?

module Thing
  def self.pub; puts "Public method"; end
  private
  def self.priv; puts "Private method"; end
end

そこにあるprivateは効果がないようですThing.privを問題なく呼び出すことができます。

役に立ちましたか?

解決

すべてのロジックを処理するモジュール内にクラスを作成することにより、これを行う最善の方法(および既存のライブラリの作成方法)を考えると、モジュールは便利なメソッドを提供するだけです。例えば、

module GTranslate
  class Translator
    def perform( text ); 'hola munda'; end
  end

  def self.translate( text )
    t = Translator.new
    t.perform( text )
  end
end

他のヒント

Module.private_class_methodもあり、これはおそらくより多くの意図を表します。

module Foo
  def self.included(base)
    base.instance_eval do
      def method_name
        # ...
      end
      private_class_method :method_name
    end
  end
end

質問のコードの場合:

module Thing
  def self.pub; puts "Public method"; end
  def self.priv; puts "Private method"; end
  private_class_method :priv
end

Ruby 2.1以降:

module Thing
  def self.pub; puts "Public method"; end
  private_class_method def self.priv; puts "Private method"; end
end
module Writer
  class << self
    def output(s)
      puts upcase(s)
    end

    private

    def upcase(s)
      s.upcase
    end
  end
end

Writer.output "Hello World"
# -> HELLO WORLD

Writer.upcase "Hello World"
# -> so.rb:16:in `<main>': private method `upcase' called for Writer:Module (NoMethodError)

<!> quot; included <!> quot;を使用できます。モジュールが混在しているときに派手なことをする方法

module Foo
  def self.included(base)
    class << base 
      def public_method
        puts "public method"
      end
      def call_private
        private_method
      end
      private
      def private_method
        puts "private"
      end
    end
  end
end

class Bar
  include Foo
end

Bar.public_method

begin
  Bar.private_method
rescue
  puts "couldn't call private method"
end

Bar.call_private

残念ながら、privateはインスタンスメソッドにのみ適用されます。プライベート<!> quot; static <!> quot;を取得する一般的な方法。クラス内のメソッドは次のようなことを行います:

class << self
  private

  def foo()
   ....
  end
end

確かに、モジュールでこれをやったことはありません。

良い方法はこのようなものです

module MyModule
  class << self
    def public_method
      # you may call the private method here
      tmp = private_method
      :public
    end

    private def private_method
      :private
    end
  end
end

# calling from outside the module
puts MyModule::public_method

Railsでこれを行うことで見つけた最良のパターンは、プライベートメソッドを持ち、代わりにシングルトンクラスを使用するモジュールを放棄することです。正しくないように感じますが、動作し、この質問で私が見た他の例よりもきれいに見えます。

これに関する他の意見を聞きたいです。

例:

ErrorService.notify("Something bad happened")

class ErrorService
  include Singleton

  class << self
    delegate :notify, to: :instance
  end

  def notify(message, severity: :error)
    send_exception_notification(message)
    log_message(message, severity)
  end

  private

  def send_exception_notification(message)
    # ...
  end

  def log_message(message, severity)
    # ...
  end
end

クラス変数/定数内にラムダとしてメソッドを保存することはどうですか?

module MyModule
  @@my_secret_method = lambda {
    # ...
  }
  # ...
end

テスト用:
UPD:6年後のこのコードの大規模な更新は、プライベートメソッドをより明確に宣言する方法を示していますd

module A
  @@L = lambda{ "@@L" }
  def self.a ; @@L[] ; end
  def self.b ; a ; end

  class << self
    def c ; @@L[] ; end
    private
    def d ; @@L[] ; end
  end
  def self.e ; c ; end
  def self.f ; self.c ; end
  def self.g ; d ; end
  def self.h ; self.d ; end

  private
  def self.i ; @@L[] ; end
  class << self
    def j ; @@L[] ; end
  end

  public
  def self.k ; i ; end
  def self.l ; self.i ; end
  def self.m ; j ; end
  def self.n ; self.j ; end
end

for expr in %w{ A.a A.b A.c A.d A.e A.f A.g A.h A.i A.j A.k A.l A.m A.n }
  puts "#{expr} => #{begin ; eval expr ; rescue => e ; e ; end}"
end

次のように表示されます:

A.a => @@L
A.b => @@L
A.c => @@L
A.d => private method `d' called for A:Module
A.e => @@L
A.f => @@L
A.g => @@L
A.h => private method `d' called for A:Module
A.i => @@L
A.j => @@L
A.k => @@L
A.l => @@L
A.m => @@L
A.n => @@L

1)@@Lは外部からはアクセスできませんが、ほとんどどこからでもアクセスできます
2)class << self ; private ; defは、self.を使用して外部および内部からメソッドprivate ; self.に正常にアクセスできるようにしますが、それなしではできません-これは奇妙な
3)private ; class << selfおよび<=>はメソッドをプライベートにしません-<=>

の有無にかかわらずアクセス可能です

プライベートモジュールまたはクラスを作成する

定数は決してプライベートではありません。ただし、モジュールまたはクラスを定数に割り当てずに作成することは可能です。

したがって、:private_class_methodの代わりに、プライベートモジュールまたはプライベートクラスを作成し、パブリックメソッドまたはパブリックメソッドを定義します。

module PublicModule
  def self.do_stuff(input)
    @private_implementation.do_stuff(input)
  end

  @private_implementation = Module.new do
    def self.do_stuff(input)
      input.upcase # or call other methods on module
    end
  end
end

使用法:

PublicModule.do_stuff("whatever") # => "WHATEVER"

Module.new および Class.new

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top