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

スポンサーリンク
スポンサーリンク
ライフスタイル関連のコンテンツ
お金 | 仕事 | 勉強 | プライベート | 健康 |
プログラミング関連のコンテンツ
C言語/C++入門 | Ruby入門 | Python入門 | プログラミング全般

以前、クラス定義でメソッドへのアクセス制限・public, private, protectedで、メソッドのアクセス指定の違いを解説したのですが、忘れっぽいのでおさらい。
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の違いが分かりやすく説明してあります。

スポンサーリンク
 
スポンサーリンク