右のようなクラスがあるとします。
(ソース:Record2.javaとRecord3.java)
Record2のshoやsuuに
- の印があります。
これは、そのメンバがprivateの
アクセス修飾指定であることを示します。
これは、クラスを
カプセル化した方がよいと
いう理由から指定したものでした。
さて、Record3に引数無しで実行するdisplay()
メソッドの追加を検討します。
このメソッドは、例えば次のように、
各インスタン変数の内容を、
1行で表示するメソッドとします。
商品コード:B05, 1000円, 75個
このdisplay()メソッドとして
次の部分コードを
Record3.java に追加して、コンパイルしてみましょう。
public void display(){ System.out.printf("\t商品コード:%s,%5d円,%4d個", sho, tanka, suu); }
コンパイルすると shoとsuuの箇所で、privateメンバなのでアクセスできないための
エラーが出ます。
つまり、スーパークラスがprivateになっていると、サブクラスでも利用できないのです。
サブクラスや、同じパッケージのクラスから利用するためには、protected
宣言する必要があります。
それで、Record2.javaのshoとsuuの宣言箇所を次のように変更します。これでコンパイルエラーはなくなります。
protectedprivateString sho; // 商品コード protectedprivateshort suu; // 数量
将来の利用のされ方によりますが、
private の他のクラスから全く使えないアクセス規制では
厳しすぎる場合、protected宣言します。
これにより、他のパッケージで、
かつRecord2のサブクラスでないクラスからアクセスできないフィールド
になります。
その意味では、ある程度のカプセル化は施されていると言えます。
同様にRecord3のフィールドも、protected に変更します。
protected int tanka; //単価
以上の変更を行ったクラス図を右記に示します。
(ソース:Record2.javaとRecord3.java)
クラス図においてprotected の印は、
# です。
参考に、上記実行結果が得られるテストプログラムを以下に示します。
import rec.Record3; public class Test { public static void main(String[] a) { Record3 rec; rec = new Record3("B05",1000,75); rec.display(); } }
Java言語において、アクセス指定は public protected 指定なし private の4通りで、次の 規則になっています。 これらは、クラス、フィールド、コンストラクタ、メソッドの前で記述します。
アクセス指定 | アクセス範囲説明 | 補足 | クラス図の記号 |
---|---|---|---|
public | 制限がなく、どのクラスからでもアクセスできる。 | クラスに指定する場合は、ファイル名を同じにしなければならない。 | + |
protected | 同じパッケージのクラスか、又はサブクラスからだけアクセス可能 | (クラスに指定することはできない) | # |
指定なし | 同じパッケージであればアクセス可能 | 一つソースファイル内に、複数のクラスを書けるが、それらは同じパッケージになる。 | ~ |
private | 同一クラスからしかアクセスできない指定 | (クラスに指定することはできない) | - |
なお、オーバーライドメソッドを作る時のアクセス修飾子は、アクセス制限を弱める方向
(例えば、スーパクラスでpublicのメンバをprotectedにする。)で変更した作り方ができません。
その逆はできません。(なお、privateメソッドは継承されない(利用できない)ので、オーバーライドではなく、まったく別のメソッドとして作る意味になります)