読者です 読者をやめる 読者になる 読者になる

第15回Yokohamarbに行ってきた

毎月恒例ですね。Yokohamarbです。

レシピブック輪読

Rubyレシピブック 第3版 303の技

Rubyレシピブック 第3版 303の技

レシピブックの輪読は「012 メソッドの呼び出し制限」を。

盛り上がったのはRubyのprotectedについて。

そもそも、RubyのprivateとprotectedはJavaなどのものと異なります。

まずはprivateから。

Javaのprivateは自クラスでしか呼び出せません。継承したクラスではprivateなメンバーは参照できません。

Rubyのprivateは関数形式でしか呼び出せません。というわけで、サブクラスからもベースクラスのprivateメソッドを呼び出せます。

class A
   def private_method
      puts "private!"
   end
   private :private_method
end

class B < A
   def b_method
      ## Aクラスのprivate methodを呼び出す
      private_method
   end
end

B.new.b_method #=> "private!"が出力される。

次にprotectedについて。

Javaのprotectedは

他ファイルの他クラスからの呼び出しをできなくする

という意味になります。

Rubyは、

そのメソッドを持つオブジェクトのメソッド定義内でないと呼び出せない

という意味になる。って書いてもわけわからんので、サンプル(るりまのパクリだけど^^;)を。irbの実行結果で。

ruby-1.9.2-p290 :001 > class Foo
ruby-1.9.2-p290 :002?>   def foo
ruby-1.9.2-p290 :003?>     p "protected!"
ruby-1.9.2-p290 :004?>     end
ruby-1.9.2-p290 :005?>   protected :foo
ruby-1.9.2-p290 :006?>   end
 => Foo 
ruby-1.9.2-p290 :007 > obj = Foo.new
 => #<Foo:0x007fee0c355550> 
ruby-1.9.2-p290 :008 > obj.foo   # => これは呼べない
NoMethodError: protected method `foo' called for #<Foo:0x007fee0c355550>
	from (irb):8
	from /Users/miyohide/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'
ruby-1.9.2-p290 :009 > class Foo
ruby-1.9.2-p290 :010?>   Foo.new.foo  # => クラス内でも呼べない
ruby-1.9.2-p290 :011?>   end
NoMethodError: protected method `foo' called for #<Foo:0x007fee0c2fcfb8>
	from (irb):10:in `<class:Foo>'
	from (irb):9
	from /Users/miyohide/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'
ruby-1.9.2-p290 :012 > class Foo
ruby-1.9.2-p290 :013?>   def bar
ruby-1.9.2-p290 :014?>     foo
ruby-1.9.2-p290 :015?>     end
ruby-1.9.2-p290 :016?>   end
 => nil 
ruby-1.9.2-p290 :017 > Foo.new.bar # => クラス内のメソッド定義内で呼べる
"protected!"
 => "protected!" 
ruby-1.9.2-p290 :018 > 

で、話題になったのが、「じゃ、Rubyのprotectedってどう使うの?」ってこと。

議論の中で出てきたのは、「今更聞けない private と protected の違い」のコメント欄に書かれていることなんだけど、う〜むって感じで。

仕様の詳細は、るりまを参照すればよいかと。
呼び出し制限

また、FAQにも記事がありました。
privateとprotectedの違いが分かりません

まとめ

いつものように、Togetterのまとめです。