おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

Rubyのアクセス制御について(protectとprivate)

なんとなく覚えてるだけだったので、きちんと調べてみました。

private

Rubyのprivateはレシーバ形式*1での呼び出しが禁止になるという意味。selfレシーバが省略された形式(関数形式)でのみ呼び出し可能*2になる。関数形式で呼び出せるということは・・・サブクラスからの呼び出しが可能であるということになる!Javaを知ってるとなんか違和感。

class HogeSuper  
  private  
  def private_method
    puts "private"
  end
end
class Hoge < HogeSuper
  def hoge
    private_method # サブクラスからprivateなメソッドを呼び出してる
  end
end
Hoge.new.hoge # => "private"

protect

protectedはレシーバ形式での呼び出しが自クラス及びサブクラスから可能になる。

privateとprotectの違い

privateで指定されているメソッドは、自分のインスタンスメソッド*3しか呼び出せないけど、protectedなら自分以外のインスタンスメソッドも呼び出せる。言葉だけだとわかりづらいので下記のコード見てください。

class HogeSuper
  
  protected  
  def protected_method
    puts "protected"
  end
  
  private  
  def private_method
    puts "private"
  end
end
class Hoge < HogeSuper
  def hoge
    protected_method # OK
    private_method # OK
    a = Hoge.new
    a.protected_method # OK
    a.private_method # Error
  end
end
Hoge.new.hoge

実行結果

protected
private
protected
a.rb:19:in `hoge': private method `private_method' called for # (NoMethodError)
	from a.rb:22

まとめ?

Rubyではあんまりprivateやprotectは使わないけど、Javaとの違いをきちんと把握しておかないといざというときにハマりそうだなーと思いました。

参考

まるごと Ruby! Vol.1

まるごと Ruby! Vol.1

たのしいRuby 第2版 Rubyではじめる気軽なプログラミング

たのしいRuby 第2版 Rubyではじめる気軽なプログラミング

20080615追記

private指定されているメソッドでも、アクセサメソッドだけはselfレシーバを指定できるようです。

privateなアクセサは例外的に「self.value = x」という形が許される - ’(rubikitch wanna be (a . lisper))

*1:obj.methodみたいな形式

*2:self.methodのように書くのもだめ

*3:またはサブクラスのインスタンスメソッド