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の違いが分かりやすく説明してあります。
- - 関連記事 -
- 特異クラスによるクラスメソッド定義・class << self ~ end
- モジュールの使い方
- クラス定義でメソッドへのアクセス制限・public, private, protected
- クラス継承
- クラス拡張
- クラス変数・クラスメソッド
- アクセスメソッド(アクセサ)をattr_reader, attr_writer, attr_accessorで定義
- アクセスメソッド(アクセサ)
- Rubyのクラス定義・initialize(コンストラクタ)
- スーパークラスとサブクラス・クラス継承
- classメソッド・オブジェクトが属するクラスを調べる
- オブジェクトのコピーを作る
- Rubyのinitializeメソッドの継承