0
0

More than 1 year has passed since last update.

privateメソッドはクラスメソッドで使えない理由から学んだことメモ

Posted at

コード例

class Hoge

 def self.xxx
   yyy
 end

 private

 def yyy
   '呼んだ?'
 end
end
Hoge.xxx
=> NameError: undefined local variable or method `yyy' for Hoge:Class

原因

  • スコープの違い
    • カレントオブジェクトが異なるため、そんなメソッドないよと言われてしまう

privateメソッドとは

「self以外のレシーバを指定して呼び出すことができないメソッド」(Ruby2.7以降)
self以外のレシーバが指定できない = 外部から呼び出しされることがないメソッド

しかし、レシーバが指定できないだけでそれ以外はpublicメソッドと変わらない。
そのため、スーパークラスのprivateメソッドをサブクラスで使用することは可能。(レシーバの指定をしなくてもメソッドが呼び出されるから)

class Hoge

  private
  
  def yyy
    '親のprivateメソッド'
  end
end

class Bar < Hoge
  def fuga
    yyy
  end
end
Baar.new.fuga => "親のprivateメソッド "

反対にpublicメソッドは、レシーバの指定ができるため外部からの呼び出しも可能

参考: https://qiita.com/kidach1/items/055021ce42fe2a49fd66

クラスメソッド内でprivateメソッドを扱いたいときはどうするか

  • 特異クラスでprivateメソッドを定義し、外部に公開しないprivateなクラスメソッドを定義する
  • このパターンもprivateなインスタンスメソッドと同様に、継承先のクラスからメソッド探索で呼び出し可能
class Hoge

  class << self
    def hoge
        yyy
    end

    private
  
    def self.yyy
      '特異クラスに定義されたprivateなクラスメソッド'
    end
  end
end

特異クラスとは

特定のインスタンスのみが持つクラスのこと(singleton class)
特異クラスとは、class << selfで定義できる
参照:https://docs.ruby-lang.org/ja/2.1.0/doc/spec=2fdef.html#class_method

NG例

private以下にself.xxxの形で定義しても外部から呼び出されてしまう。(クラスメソッドと扱いが同じ)
この場合は、private_class_methodで明示的にprivateメソッドにする必要あり

class Hoge

  private
  
  def self.yyy
    'プライベートなクラスメソッドだから呼ばれたくない!'
  end
end

class Bar < Hoge
  def self.foo
    Hoge.yyy
  end
end
Bar.foo => "プライベートなクラスメソッドだから呼ばれたくない!"
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0