下級エンジニアの綴

新しく発見したことを綴っていこうと思っています。夢はでっかく上級エンジニアになることです。

rubyの特異メソッドのprivateについて気になったから調べたのでメモ

特異メソッドでprivateなメソッドを呼ぶ方法

  • sendを使う
    • privateの特異メソッド、privateのインスタンスメソッドを関係なく呼べる
    • 最終手段な感じがするので、あまり推奨できないと思った
class A
  def self.hoge
    A.new.send(:fuga)
  end

  def self.aaa
    A.send(:bbb)
  end

  def self.bbb
    p 'bbb'
  end

  private

  def fuga
    p 'fuga'
  end

  private_class_method :bbb
end

A.hoge      # "fuga"
A.aaa       # "bbb"
A.new.fuga  # private method `fuga' called for #<A:0x007f3ac14fb2f0> (NoMethodError)
A.bbb       # private method `bbb' called for A:Class (NoMethodError)
  • private_class_methodを使う
    • 特異メソッドが少ない時はこちらを使用する
    • privateにしたいメソッドを定義した後にprivate_class_methodで定義する
class A
  def self.hogo
    fugo
  end

  def self.fugo
    p 'fugo'
  end

  private_class_method :fugo
end

A.hogo  # "fugo"
A.fugo  # private method `fugo' called for A:Class (NoMethodError)
  • class << selfを使う
    • 特異メソッドが多い時に使用する
    • 階層が1段多くなるがメソッドにclass << self~endまでに定義したメソッドが特異メソッドになる。
    • private以下に定義したメソッドは特異クラスのprivateメソッドになる
class A
  class << self
    def hoo
      foo
    end

    private

    def foo
      p 'foo'
    end
  end
end

A.hoo  # "foo"
A.foo  # private method `foo' called for A:Class (NoMethodError)