protected とprivate アクセス修飾子

右のようなクラスがあるとします。
(ソース: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の宣言箇所を次のように変更します。これでコンパイルエラーはなくなります。

	protected private String sho;	// 商品コード
	protected private short 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メソッドは継承されない(利用できない)ので、オーバーライドではなく、まったく別のメソッドとして作る意味になります)