Ruby – public/protected/private

概要

Rubyにおけるprivateprotectedは、C++やJavaでの振る舞いと一部で異なる。慣れている言語との違いというよりも、Rubyの場合言葉の概念から予想される挙動がシンプルに想起できない。

自クラス内での挙動

以下のコードで自クラス内での挙動を確認する。

直接呼出し

まず次のメソッドに着目する。

これらのメソッドを、インスタンスから直接呼び出した結果。publicメソッドは呼び出せるが、private/protectedメソッドは隠蔽されている。これは想定通り。

関数アクセス

次に、同一クラスの中でこれら3つのメソッドに関数としてアクセスするメソッドの挙動を見てみる。

これらのメソッドをインスタンスから呼び出した結果はすべてエラー無く、同一クラス内からは全て利用可能なことがわかる。

レシーバーアクセス

さらに、関数としてのアクセスではなく、レシーバーのメソッドとしてアクセスするメソッドを試してみる。

同じParentClassの新たなインスタンスを生成し、これを渡してみると、privateメソッドのみエラーとなる。

継承クラスでの挙動

ParentClassの継承クラスChildClassを定義し親クラスのメソッドを呼び出すと、上と同じ結果になり、privateprotectedは隠蔽されている。

関数呼び出しの場合、親クラスのメソッドに全てアクセス可能で、これも自クラス呼び出しと同じ。

別のChildClassのインスタンスを生成し、これをレシーバーとしてメソッドを呼び出すと、privateのみエラーとなる。

なお、関数呼び出し、レシーバー呼び出しの各internalメソッドをChildClass内でオーバーライドしても結果は同じになる。

まとめ

これらをまとめると次のようになる。

public protected private
自クラス
直接コール
× ×
自クラス
関数コール
自クラス
レシーバー
×
継承クラス
直接コール
× ×
継承クラス
関数コール
継承クラス
レシーバー
×

すなわち、public想定通り、関数コールの場合protectedprivateも自クラス・継承クラスに関わらず実行可能。レシーバー呼び出しの場合protectedは実行可能だがprivateは実行不可で、これも自クラス・継承クラスに関わらない。