Rubyは,JavaやC++と同様に,クラスの利用者がクラスの内部の実装に必要以上に依存しないように,アクセス制御を行うことができます。
クラスのメンバ変数へのアクセスは,同名のメソッドによって行われるので,メソッドのアクセスをコントロールすれば十分です。
Rubyでは,Module#public, Module#protected,Module#privateというメソッドを用いて(予約語ではありません),アクセス制御を行います。これらのメソッドを引数なしで呼び出すと,現在のスコープのデフォルト・アクセス可能性(accessibility)を変更し,以降のメソッド定義は,そのアクセス可能性で行われます。メソッド名のシンボルを引数にして呼び出すと,そのメソッドのアクセス可能性を変更します。
メソッドのアクセス可能性は動的に変更でき,アクセス可能かどうかの判定は実行時に行われます。すなわち,実際にメソッド呼び出しを行うときに,アクセス可能かどうか判定されます。
publicメソッド,protectedメソッド,privateメソッドの呼び出しは,次のような制限があります。
protectedメソッドの例です。サブクラスではないクラスから呼び出そうとするとNameErrorが発生します。
2| class B 3| protected 4| def foo(x) 5| p x 6| end 7| end 8| 9| class D < B 10| def bar(x) 11| foo(x * 2) 12| end 13| end 14| 15| class O 16| def baz(x) 17| B.new.foo(x * 3) #=> NameError 18| end 19| end 20| D.new.bar(1) #=> 2 21| O.new.baz(2)
privateメソッドの例です。同じクラス内でも別のインスタンスであればエラーになります。
1| class Foo 2| def c1 3| pri 4| end 5| 6| def c2(o) 7| o.pri #=> NameError 8| end 9| 10| private 11| def pri 12| p true 13| end 14| end 15| 16| obj = Foo.new 17| obj.c1 #=> true 18| obj.c2(Foo.new)
Module#public, Module#protected,Module#privateによって陽にメソッドのアクセス可能性を変更したり,スコープのデフォルト・アクセス可能性を変更しない場合,クラス定義の中でのデフォルト・アクセス可能性はpublicです。ただし,例外的にinitializeメソッドは,常にprivateになります。
クラス定義の外でメソッドを定義するとき(関数形式,Kernelモジュールのメソッドになる),デフォルトのアクセス可能性はprivateです。これがどこからでも呼べるのは,ObjectクラスがKernelモジュールをincludeしており,クラスはすべてObjectのサブクラスだからです。