5-2: パッケージとアクセス制御


・ Javaではアクセス制御においてもクラスの存在が一番の基本です。 「クラスの内部にあるか外部にあるか?」 をアクセス制御の基準とするのは自然な考え方でしょう。
 ただしクラスの枠によるアクセス制御は少し「極端すぎる」きらいがあります。 いったんアクセスに制限を加えると決めたら、 そのデータは他のすべてのクラスに対してアクセスが禁止されてしまいます。 逆に1個でもアクセスを許可したい相手のクラスが存在するならば、 他のすべてのクラスに対してもアクセスを許可しなくてはいけません。 実際のアプリケーションの開発の中では、 ある特定のクラスに対してはアクセスを許可するが、 他のクラスに対しては禁止するというような制御ができれば便利でしょう。 上のような仕組みを実現するには、 「仲間のクラス」を識別するための何か新しいルールを導入することが前提になります。 このために Javaはパッケージという概念を導入します。
 この他にパッケージの他にクラスをグループ分けする手段として 継承関係がありました。 継承関係にあるクラスどおしが、 他のクラスに比べて深い関係にあるのは明らかです。 Javaではサブクラスのデータへのアクセスの許可を指定する仕組みも用意されています。

・ Javaにはクラスのメンバーに対するアクセス制御を表すキーワードが 3種類ありました。public, protected, privateです。 また、この他にキーワードを省略した場合の 「デフォルトのアクセス制御」があります。 この4つのアクセスモードの意味を簡単にまとめると、 下記の表のようになります。

アクセス制御とその許可範囲
publicproteced指定なしprivate
クラスの内部
同一のパッケージ×
サブクラス内××
無関係なクラス×××

パッケージを指定しなかった場合には、クラスは「名前なしのパッケージ」に 共通して含まれていると見なされます。 したがって、protected の指定も指定なしのデファルトのアクセス制御でも public と実質的な違いはありません。 パッケージを使用しないクラス間では、 publicとprivate の違いしか存在しないわけです。 (他の明示的にパッケージを宣言したクラスからのアクセス権には違いがあります。)

もう一つ勘違いしてはいけない点があります。 protected や private の宣言によって、 内部のデータにアクセスする手続きが完全に禁止されるわけではない、 ということです。 禁止されるのは「.(ピリオド記号)」による直接のアクセスにすぎません。 実際 Javaでは次のような記述法がしばしば用いられます。


/** privateなフィールド */
    private int x;

/** フィールドにアクセスする publicなメソッド */
    public int getX() { return x; }

この場合、他のクラスから object.x という形式でデータにアクセスすることは できませんが、object.getX() という方法で値を取り出すことは自由に行えます。