Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Rubyのクラスメソッドはインスタンスメソッドと同じようにprivateにならない

More than 5 years have passed since last update.

これも他の言語から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

jnchito
SIer、社内SEを経て、ソニックガーデンに合流したプログラマ。 「プロを目指す人のためのRuby入門」の著者。 http://gihyo.jp/book/2017/978-4-7741-9397-7 および「Everyday Rails - RSpecによるRailsテスト入門」の翻訳者。 https://leanpub.com/everydayrailsrspec-jp
https://blog.jnito.com/
sonicgarden
「お客様に無駄遣いをさせない受託開発」と「習慣を変えるソフトウェアのサービス」に取り組んでいるソフトウェア企業
http://www.sonicgarden.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away