酒と泪とRubyとRailsと

Ruby on Rails と Objective-C は酒の肴です!

Rubyのprotected Methodってどんなときに使うの?

2/1(月)に開催された「Sendagaya.rb」に参加してきたので、その際に教えてもらった、「protected」ってどんなときに使うのってお話です。 間違っている可能性も過分にありますので、間違ってたら偉い人教えて下さい。


public、private、protected について

クラス/メソッドの定義

- public に設定されたメソッドは制限なしに呼び出せます
- private に設定されたメソッドは関数形式でしか呼び出せません
- protected に設定されたメソッドは、そのメソッドを持つオブジェクトがselfであるコンテキスト(メソッド定義式やinstance_eval)でのみ呼び出せます

サンプルですが、 「Protected Methods and Ruby 2.0 | Tenderlovemaking」 を拝借させていただきつつ紹介。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# public protected, private メソッドを持つクラス
class MyClass
  # Internal Visibility
  def sample_instance_method
    # public
    puts public_method #=> OK
    puts self.public_method #=> OK

    # protected
    puts protected_method #=> OK
    puts self.protected_method #=> OK

    # private
    puts private_method #=> OK
    # privateメソッドはselfをつけてはいけない
    puts self.private_method #=> raises NoMethodError
  end

  def public_method; 'public_method' end

  protected
  def protected_method; 'protected_method' end

  private
  def private_method; 'private_method' end
end

# Internal Visibility
MyClass.new.sample_instance_method

# External Visibility
my_class = MyClass.new
puts my_class.public_method    # => OK
puts my_class.protected_method # => raises NoMethodError
puts my_class.private_method   # => raises NoMethodError

じゃあどんなときに、protectedを使えるかというと;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Sample
  def == other
    if self.class == other.class
      internal == other.internal
    else
      super
    end
  end

  protected
  def internal; :sample; end
end

Sample.new == Sample.new #=> true

このように == メソッドを作る時などに、レシーバをつけつつ、外部に内部のデータのgetterを公開したくない場合などに有効そう。

あとがき

考えたことなかったです。めっちゃ勉強になりました!

Sendagaya.rb最高!

2/1(月)の、Sendagaya.rbはこんなことをしました。

  • メタプログラミングRubyの輪読(2章)
  • ActiveRecord 5.0.0.beta1.1のCHANGELOGを読む

@tkawaさんの解説がめっちゃ丁寧で分かりやすかったです!


おすすめの書籍