Movatterモバイル変換


[0]ホーム

URL:


LoginSignup
645

Go to list of users who liked

527

Share on X(Twitter)

Share on Facebook

Add to Hatena Bookmark

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ruby の private と protected 。歴史と使い分け

Last updated atPosted at 2014-08-18

概要

Ruby の private と protected の歴史と使い分けについて説明します。

いろんなところで断片的に書かれていることなのですが、有益な情報を
一箇所に集めると自分の理解が深まりそう=>他の人にも役立つかな?
と思ったのでまとめてみました。

具体的には、伊藤淳一さんのブログ・るりま・Rubyメーリングリストの内容を
一箇所にまとめた上で、私が書いたサンプルコードを少し足した内容になっています。

ちなみに Java や C# 畑の人が Ruby の private / protected を使って驚いた、
的な情報が多いですが、私も例にもれず Java => Ruby 勢で驚いたパターンです。

Java の private と protected

  • public => どこからでもアクセス可能
  • protected => クラス内、同一パッケージ、サブクラスからアクセス可
  • private => クラス内のみアクセス可能

制限無く公開したいなら public 。
基本的に外部からは隠蔽するが、サブクラスやパッケージ内からのみ利用させたい場合は protected 。
基本的に外部からは隠蔽し、クラス内からのみ利用させたい場合は private 。

という使い分けになっていて、かなり分かりやすく、使い分ける目的も明確です。

今回の話には関係ありませんが、アクセス修飾子を省略した場合には default というスコープもあります。

  • default => クラス内、同一パッケージからアクセス可

Ruby の private と protected

るりまを確認

るりまでは下記のように説明されています。
http://docs.ruby-lang.org/ja/2.1.0/doc/spec=2fdef.html#limit

  • public => public に設定されたメソッドは制限なしに呼び出せます。
  • protected => protected に設定されたメソッドは、そのメソッドを持つオブジェクトが self であるコンテキスト(メソッド定義式や instance_eval )でのみ呼び出せ ます。
  • private => private に設定されたメソッドは関数形式でしか呼び出せません。

※便宜上、るりまとは表記順を変えてあります。(スコープの範囲が広い順にした方が分かりやすいと思ったので)

説明だけだとピンと来ないかもしれないので、サンプルコードを提示します。

private と protected の動作を確認

require'english'classScopeResearchClassdefpublic_method'public'enddefuse_protected(other)putsother.protected_methodenddefuse_private(other)other.private_methodrescueputs$ERROR_INFOenddefinternal_use_private_and_protectedputsprotected_methodputsprivate_methodenddefinternal_use_private_and_protected_with_recieverputsself.protected_methodself.private_methodrescueputs$ERROR_INFOendprotecteddefprotected_method'protected'endprivatedefprivate_method'private'endendpc1=ScopeResearchClass.newpc2=ScopeResearchClass.newbeginpc1.protected_methodrescue# protected は外部からは呼び出せずにエラーputs$ERROR_INFOendbeginpc1.private_methodrescue# private は外部からは呼び出せずにエラーputs$ERROR_INFOend# private / protected ともに内部から利用可能pc1.internal_use_private_and_protected# protected は レシーバーつきでも呼び出し可能# private は レシーバーつきだと呼び出せずpc1.internal_use_private_and_protected_with_recieverclassHogedefcan_not_use_external_protected_method(other)other.protected_methodrescueputs$ERROR_INFOendend# 関係ないクラス内からは呼び出せないことを確認Hoge.new.can_not_use_external_protected_method(pc2)# protected メソッドは自クラスに別インスタンスを渡しても呼び出し可能pc1.use_protected(pc2)# private メソッドは自クラスに別インスタンスを渡した場合、レシーバーの指定が出来ないのでエラーになるpc1.use_private(pc2)classChildProtectedClass<ScopeResearchClassdefuse_protected_from_child(other)putsother.protected_methodendend# protected メソッドはサブクラスに別インスタンスを渡しても呼び出し可能ChildProtectedClass.new.use_protected_from_child(pc2)
  • 出力
protected method `protected_method' called for #<ScopeResearchClass:0x0000060044c770>private method `private_method' called for #<ScopeResearchClass:0x0000060044c770>protectedprivateprotectedprivate method `private_method' called for #<ScopeResearchClass:0x0000060044c770>protected method `protected_method' called for #<ScopeResearchClass:0x0000060044c748>protectedprivate method `private_method' called for #<ScopeResearchClass:0x0000060044c748>protected

protected を使うべき状況

protected を使うべき状況について、るりまにサンプルコードが掲載されていますが、
サンプルコードに少し補足をして、実行して動きを確認できるプログラムにしてみます。

classFoodef_val@valendprotected:_valdefop(other)# other も Foo のインスタンスを想定# _val が private だと関数形式でしか呼べないため# このように利用できないself._val+other._valendendf1=Foo.newf1.instance_variable_set(:@val,1)# => @val に無理やり 1 を設定f2=Foo.newf2.instance_variable_set(:@val,2)# => @val に無理やり 2 を設定putsf1.op(f2)# => 3

Ruby の private と protected の歴史

伊藤淳一さんの素晴らしいブログエントリに Ruby のパパ「 Matz 」さんとのやりとりが
まとまっています。
http://blog.jnito.com/entry/20120315/1331754912

  • Matz さん曰く
Rubyのprivateの発想の元になったのはSmalltalkの「privateカテゴリ」です。使わないでね、というだけでアクセスできちゃう。Rubyはそれよりは若干強制力があります。Rubyの反C++・親Smalltalkの設計思想が垣間見えますね後でprotectedを追加したのもまずかった。これでC++とキーワードが同じでも意味がズレてることになってしまったので。

private と protected の使い分けに関する Matz さんの分かりやすい説明

Rubyのメーリングリストのやりとりより。
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/7669

  • Matz さん曰く
つまり,privateは自分からしか見えないメソッドであるのに対して,protectedは一般の人からは見られたくないが,仲間(クラスが同じオブジェクト)からは見えるメソッドです.protectedは例えば2項演算子の実装にもう一方のオブジェクトの状態を知る必要があるか調べる必要があるが,そのメソッドをpublicにして,広く公開するのは避けたいというような時に使います.

Ruby のメソッドの公開範囲の決定に関するマトリクス

スコープ全体に公開したい外部から隠蔽したいレシーバーを仲間が利用する
public×
protected×
private××

※仲間=自クラスかサブクラスのレシーバー

参照

645

Go to list of users who liked

527
3

Go to list of comments

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
645

Go to list of users who liked

527

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?


[8]ページ先頭

©2009-2025 Movatter.jp