![]() ![]() ![]() ![]() |
オブジェクト、クラス、インタフェース |
「保留:我々はデフォルトのアクセスを「味方」と呼んでいる、しかし私はそれが実際に他に何かの呼び出し方を耳にする」。クラスの利点の1つは、クラスが他のオブジェクトによるアクセスからメンバ変数とメソッドを守ることができるということである。 なぜこれは重要であるか? まあ、これを考慮してみる。 クラスを書いていて、例えばそれが会社の社員の記録や収入計算書のようなもので、それがあらゆる種類の秘密情報を含むデータベース上への問合せを意味する。
公的にアクセス可能なメソッドと変数がサポートするクラスに含まれる特定の情報と問い合わせは、そのシステムの他のオブジェクトに使われてもいいが、単に個人用のクラスに含まれる問い合わせは、そのクラスの操作だけをサポートする。これは保護すべき情報があるからである。言語レベルで個人用変数とメソッドを保護し、他のオブジェクトからのアクセスを拒否できることが望ましい。
Java では、クラスの変数とそのメソッドを宣言する時に、それら両方を保護するためにアクセス指示子を使用することができる。 Java 言語は、メンバ変数とメソッドのために 4 つのアクセスレベルをサポートする。それらは private、 protected、 public、そして指定されなければ「friendly」である。
注釈: Java 言語の1.0のリリースでは、5つのアクセスレベルをサポートした。上記の 4 つに加えて
private protected
である。private protected
アクセスレベルは1.0以降のバージョンではサポートされない。もう Java プログラムでそれを使用するべきではない。次のチャートは各指示子が許可するアクセスレベルを示す。
1列目は、クラス自身がアクセス指示子が定義したメンバにアクセス権を持っていいるかどうかを示す。 見てわかるように、クラスは常にそれ自身のメンバにアクセスできる。 2 列目はクラスのサブクラスが(どのパッケージにあるかにかかわらず)、メンバにアクセスできるかどうかを示す。 3列目はクラスと同じパッケージのクラスが(それらの家柄にかかわらず)、メンバにアクセスできるかどうかを示す。 4列目は、すべてのクラスがメンバにアクセスできるかどうかを示す。指示子クラスサブクラスパッケージ ----------------------------------------------------- private X protected X X* X public X X X X friendly X Xprotected /サブクラスの所に”*”があることに注意しよう。この特定のアクセスの場合は特別な警告を持っているので、後で詳細に説明する。
各アクセスレベルの詳細を説明する。
Private
もっとも厳しいアクセス制限レベルは private である。 private のメンバは、それが定義されるクラスにのみアクセス可能である。 そのクラスだけが使えるメンバを宣言するために、このアクセスレベルを使用する。 これには、外部からアクセスされた場合にオブジェクトを矛盾状態にするための情報を含む変数、あるいは外部により起動された場合にオブジェクトまたは実行中であるプログラムを危険状態にするメソッドなどがある。 private のメンバは、決して誰にも話さない秘密のようなものである。private のメンバを宣言するには、その宣言で
private
キーワードを使用する。 次のクラスは、1つの private メンバ変数と1つの private メソッドを含んでいる。Alpha 型のオブジェクトは、class Alpha { private int iamprivate; private void privateMethod() { System.out.println("privateMethod"); } }iamprivate
変数を検査したり変更することができ、privateMethod()
を起動することができる。しかし他の型のオブジェクトではできない。 例えば、 Beta クラスを定義する。Beta は Alpha 型ではないので、class Beta { void accessMethod() { Alpha a = new Alpha(); a.iamprivate = 10; // illegal a.privateMethod(); // illegal } }iamprivate
変数にアクセスしたり、 Alpha 型のオブジェクト上にprivateMethod()
を起動することができない。クラスがアクセス権を持っていないメンバ変数にアクセスしようと試みていることを知るができる。コンパイラは次に類似したエラーメッセージをプリントして、プログラムをコンパイルすることを拒否する。
同様に、プログラムがそれがアクセス権を持っていないメソッドにアクセスしようと試みると、次のようなコンパイラエラーが表示される。Beta.java:9: Variable iamprivate in class Alpha not accessible from class Beta. a.iamprivate = 10; // illegal ^ 1 error初心者の Java プログラマが、Alpha オブジェクトが別の Alpha オブジェクトの private メンバをアクセスできるかどうか聞くかも知れない。 これは以下で例証する。 Alpha クラスが、現在の Alpha オブジェクト(Beta.java:12: No method matching privateMethod() found in class Alpha. a.privateMethod(); // illegal 1 errorthis
)と別のiamprivate
変数に基づいたオブジェクトとを比較したインスタンスメソッドを含んでいると仮定する。これは完全に正当である。 同じ型のオブジェクト同士が互いに一方の private のメンバにアクセスできる。 これは、アクセス制限がオブジェクトレベル(このクラスの特定のインスタンス)よりむしろクラスあるいは型のレベル(すべてのクラスのインスタンス)において適用されるからである。class Alpha { private int iamprivate; boolean isEqualTo(Alpha anotherAlpha) { if (this.iamprivate == anotherAlpha.iamprivate) return true; else return false; } }注意:
this
は現在のオブジェクトを参照する Java 言語キーワードである。this
の使用方法の詳細については、、 メソッド本体を参照のこと。Protected
次のアクセスレベル指示子は protected である。protected により、クラス自身、サブクラス(前述した警告つき)、および同パッケージのすべてのクラスがメンバにアクセスすることができる。 無関係なクラスではなく、メンバにアクセスするのがクラスのサブクラスにとって適切な時は、 protected アクセスレベルを使用する。 protected メンバは家族の秘密のようである。つまり家族全体が知っていても気にしないが、家族以外の誰にも知られたくないということである。protected メンバを宣言するためには、キーワード
protected
を使用する。 最初に、protected 指示子が同じパッケージのクラスへのアクセスにどのように影響を与えるかを考える。パッケージ名 Greek 内に宣言されていて、その中で宣言されたprotected メンバ変数と protected メソッドを持つ Alpha クラスの次のバージョンを考慮する。
ここで、クラス Gamma が同じく Greek パッケージのメンバであると宣言されている(そして Alpha のサブクラスではない)と仮定する。 Gamma クラスは、合法的に Alpha オブジェクトのpackage Greek; class Alpha { protected int iamprotected; protected void protectedMethod() { System.out.println("protectedMethod"); } }iamprotected
メンバ変数にアクセスすることができ、合法的にそのprotectedMethod ()
を起動することができる。それはかなり簡単である。 では、protected 指示子が Alpha のサブクラスのアクセスにどのような影響を与えるか調査する。package Greek; class Gamma { void accessMethod() { Alpha a = new Alpha(); a.iamprotected = 10; // legal a.protectedMethod(); // legal } }新規のクラス、 Delta を導入する。Delta は Alpha から生じたが、異なるパッケージ − Latin − にいる。 Delta クラスは
iamprotected
とprotectedMethod ()
の両方をアクセスすることができるが、Delta 型あるいはそのサブクラスのオブジェクト上に限定される。 Delta クラスは Alpha 型のオブジェクト上でiamprotected
あるいはprotectedMethod()
をアクセスすることができない。次のコード例にあるaccessMethod()
がAlpha 型のオブジェクトのiamprotected
メンバ変数にアクセスしようとするのは、不正である。Delta 型のオブジェクトのiamprotected
メンバ変数にアクセスするのは正当である。 同様に、accessMethod()
が Alpha オブジェクトのprotectedMethod()
を呼び出すのは不正である。もしクラスがサブクラスであり、 かつ protected メンバを持っているクラスと同じパッケージにいるのであれば、クラスは protected メンバにアクセスできる。import Greek. *; package Latin; class Delta extends Alpha { void accessMethod(Alpha a, Delta d) { a.iamprotected = 10; // illegal d.iamprotected = 10; // legal a.protectedMethod(); // illegal d.protectedMethod(); // legal } }Public
最も容易なアクセス指示子は public である。 任意のクラスやパッケージにでも、クラスの public メンバにアクセスできる。 外部が public メンバを使用して、このようなアクセスが望ましい結果を作り出すことができる場合に限り、 public メンバを宣言する。 ここに個人的あるいは家族の秘密がない。これは他人が知っているのを気にしない要素のためである。public メンバを宣言するためには、キーワード
public
を使用する。 例えば、もう一度 Beta クラスを書き換えて、 Alpha と異なるパッケージにそれを置き、それが完全に Alpha と無関係である(サブクラスではない)ことを確認する。package Greek; class Alpha { public int iampublic; public void publicMethod() { System.out.println("publicMethod"); } }上記のコードから見て分かるように、 Beta が合法的に Alpha クラスのimport Greek.*; package Roman; class Beta { void accessMethod() { Alpha a = new Alpha(); a.iampublic = 10; // legal a.publicMethod(); // legal } }iampublic
変数を検閲したり、変更したり、また合法的にpublicMethod()
を呼び出したりすることができる。Friendly
最後のアクセスレベルは、明示的にメンバのアクセスを他のレベルに設定しない場合に得るものである。 このアクセスレベルにより、クラスと同じパッケージにあるクラスは、メンバにアクセスすることができる。 アクセスのこのレベルでは、同じパッケージのクラスは信頼できる友人であると想定する。 この信頼のレベルは、もっとも近い友人たちに及ぶが、家族さえも信用していないようなものである。例えば、 Alpha クラスのこのバージョンが「友好的な(friendly)」メンバ変数と「友好的な」メソッドを宣言する。 Alpha は Greek パッケージにある。
Alpha クラスはpackage Greek; class Alpha { int iamfriendly; void friendlyMethod() { System.out.println("friendlyMethod"); } }iamfriendly
とfriendlyMethod()
の両方にアクセスできる。 さらに、Alpha と同じパッケージ内に宣言するすべてのクラスもiamfriendly
とfriendlyMethod()
にアクセスできる。 両方の Alpha と Beta が Greek パッケージの一部として宣言されたと仮定する。その時 Beta は示すように、合法的にpackage Greek; class Beta { void accessMethod() { Alpha a = new Alpha(); a.iamfriendly = 10; // legal a.friendlyMethod(); // legal } }iamfriendly
とfriendlyMethod()
にアクセスすることができる。
![]() ![]() ![]() ![]() |
オブジェクト、クラス、インタフェース |