private, protected アクセス指定の違い

はてなブックマークに追加はてなブックマーク Yahoo!ブックマークに登録 ニフティクリップに追加 Livedoor クリップに追加 BuzzurlにブックマークBuzzurlにブックマーク Twitterに投稿  

以前、クラス定義でメソッドへのアクセス制限・public, private, protected - Ruby入門勉強ルームで、メソッドのアクセス指定の違いを解説したのですが、忘れっぽいのでおさらい。
Rubyの場合、privateとprotectedの違いが混乱しやすいので、もう一度確認しておきます。
動作確認は、Ruby1.8.6のバージョンで行いました。

まずは、PHPでの動作を見てみることにします。

<?php
class Parent_k {
  protected function hoge() {
    echo "true";
  }
}
 
class Child extends Parent_k {
  public function fuga() {
    $this->hoge();
  }
}
 
$child = new Child;
$child->fuga();
?>

実行結果。→ http://codepad.org/2uskvMeL

true

今度は、protectedだったメソッドをprivateにしてみる。

<?php
class Parent_k {
  private function hoge() {
    echo "true";
  }
}
 
class Child extends Parent_k {
  public function fuga() {
    $this->hoge();
  }
}
 
$child = new Child;
$child->fuga();
?>

実行結果。→http://codepad.org/pmZRGxxH

Fatal error: Call to private method Parent_k::hoge() from context 'Child' on line 10

スーパークラスのメソッドを、private指定にしたことで、サブクラスから呼び出すことができなくなりました。
では次、本題のRubyでの動作。

class Parent
  protected
  def method
    p true
  end
end
 
class Child < Parent
  public
  def call_method
    method
  end
end
 
Child.new.call_method

実行結果。→http://codepad.org/4vcRYoE2

true

PHPのときと同様に、Ruby版でも、スーパークラスのメソッドの、protctedをprivateに変更してみる。

class Parent
  private
  def method
    p true
  end
end
 
class Child < Parent
  public
  def call_method
    method
  end
end
 
Child.new.call_method

実行結果。→http://codepad.org/suw9aJ0b

true

PHPに慣れていると、この動作に驚いてしまうのですが、スーパークラスのメソッド(methodメソッド)がprivate指定されていても、サブクラスでの呼び出し(methodメソッド)が、.ドット無しの呼び出し(つまり、レシーバ指定をしない呼び出し)であれば、呼び出せるようになっている。
たとえば、サブクラスのcall_methodを・・・

  def call_method
    self.method
  end

と、レシーバにselfを指定してみると、エラーになりました。→http://codepad.org/5nfpq6w8
さらに、以下の例を試してみる。

class Parent
  protected
  def method
    p true
  end
 
  public
  def call_method(p)
    p.method
  end
end
 
Parent.new.call_method(Parent.new)

実行結果。→http://codepad.org/8ANA6cWD

true

protected の場合は、レシーバにインスタンスを指定して呼び出せる。
以下、privateに変更した場合。

class Parent
  private
  def method
    p true
  end
 
  public
  def call_method(p)
    p.method
  end
end
 
Parent.new.call_method(Parent.new)

実行結果。→http://codepad.org/YLLkfT9G

Line 9:in `call_method': private method `method' called for #<Parent:0x401bf93c> (NoMethodError)
    from t.rb:13

やはり、レシーバを指定しまうと、エラーになります。
以上、ちょっと分かりにくいRubyのprivateとprotectedの違いのおさらいでした。

参考:言語編
JavaとRubyの違いが分かりやすく説明してあります。


日時: 2009年06月05日 23:40
コメントを投稿






トラックバック

■この記事のトラックバックURL:
http://www.mapee.jp/mpe334/mt-tb.cgi/480

この記事にトラックバックされる方は、参照先が分かるようにするために、「private, protected アクセス指定の違い」へのリンクをお願いいたします。
以下のHTMLタグをトラックバック送信元ページ内に挿入して下さい。



※この記事へのリンクがない、また関連のないページからのトラックバックは反映されませんので、ご了承下さい。






あわせて読みたいブログパーツ
フィードメーター - Ruby勉強ルーム