これも他の言語からRubyにやってきた人は間違えやすいかも。
private以下で定義したクラスメソッドはインスタンスメソッドと同じようにprivateになりそうな気がしますが、実はpublicのままです。
private_class_method
でそのメソッドを指定するか、特異クラスの中で定義する必要があります。
require 'rspec'
describe 'private class method' do
context '1. when use private keyword' do
class PrivateKeyword
def a_public_instance_method; end
def self.a_public_class_method; end
private
def a_private_instance_method; end
def self.a_private_class_method; end
end
let(:instance) { PrivateKeyword.new }
specify { instance.respond_to?(:a_public_instance_method).should be_true }
specify { PrivateKeyword.respond_to?(:a_public_class_method).should be_true }
specify { instance.respond_to?(:a_private_instance_method).should be_false }
#Maybe surprising!!
specify { PrivateKeyword.respond_to?(:a_private_class_method).should be_true }
end
context '2. when use private_class_method' do
class PrivateClassMethod
def self.a_private_class_method; end
private_class_method :a_private_class_method
end
# Should be private
specify { PrivateClassMethod.respond_to?(:a_private_class_method).should be_false }
end
context '3. when use singleton class' do
class InSingletonClass
class << self
def a_public_class_method; end
private
def a_private_class_method; end
end
end
specify { InSingletonClass.respond_to?(:a_public_class_method).should be_true }
# Should be private
specify { InSingletonClass.respond_to?(:a_private_class_method).should be_false }
end
end
$ rspec private_class_method_spec.rb
.......
Finished in 0.00232 seconds
7 examples, 0 failures
ちなみにprivateなクラスメソッドがそれほど多くないなら、2番目のprivate_class_method
を使う方がシンプルでいいと思うんですが、どうでしょうか?
そもそもあまりクラスメソッドが多いと、本当にオブジェクト指向プログラミングできてますか?ということになりそうですし。
###参考
Privateメソッドに関連する話として、「JavaやC#の常識が通用しないRubyのprivateメソッド」というタイトルで以前ブログを書きました。
http://junichiito.hateblo.jp/entry/20120315/1331754912