コード例
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 => "プライベートなクラスメソッドだから呼ばれたくない!"