クラスの継承
継承におけるアクセス制御
継承させたいメンバは protected で書きましょう
目次
1. 継承するなら protected 以上
スーパークラスを作る際には、メンバのアクセス修飾子に注意してください。
private は、継承先(サブクラス)からアクセスすることができません。
カプセル化の観点から、インスタンス変数に private を付与するのは
とても良いことです。
ただ、継承先に新しいメソッドを作って、そこから参照したい変数には、
protected 以上のアクセス修飾子を付与する必要があります。
protected?
初耳っすね。
あ、えっと、
実は、むか~し出てきた。
ホントさわりだけ。
アクセス制御
スーパークラスの private なメンバは、サブクラスから参照できません。
protected を活用しましょう。
2. privateでも動作する例
private修飾子を使ってちょっとだけ実験してみましょう。
Animal_pv01クラスは
変数「name」を private で
書いてある。
継承するとどうなるか実験してみよう。
//Animal_pv01.java
public class Animal_pv01{
private static String group = "生き物です。";
private String name; //サブクラスから参照できません
public Animal_pv01(){
this("無名");
}
public Animal_pv01(String name){
this.name = name;
}
public static void printGroup(){
System.out.println(group);
}
public void printName(){
System.out.println(name + "だぞ! ガオー!");
}
}
サブクラス(Dog_pv01)で
super.name を参照していないから
これはセーフ。
//Dog_pv01.java
public class Dog_pv01 extends Animal_pv01{
public Dog_pv01(String name){
super(name);
}
}
↓↓↓ 以下のようなイメージ。↓↓↓
Dog_pv01 のイメージ
//Dog_pv01.java
public class Dog_pv01 extends Animal_01{
public Dog_pv01(String name){
super(name);
}
// ↓見えていないけどいる。
@Override
public void printName(){
//super.printName() の中で super.name を参照
super.printName();
}
}
//Driver_pv01.java
public class Driver_pv01{
public static void main(String[] args){
Dog_pv01 dog01 = new Dog_pv01("白いお父さん");
//このprintName() は super.printName()を呼んでいる
dog01.printName();
}
}
Animal_pv01クラス、
Dog_pv01クラス、
Driver_pv01クラス、を
wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_pv01.java
ws>java Driver_pv01
白いお父さんだぞ! ガオー!
super.printName()メソッドから super.name変数を参照するので、
name が private で問題ありません。
super.printName()メソッド自体は public である点もポイントです。
スーパークラス内での
参照なのね。
3. privateでは動作しない例
引き続き privateで実験です。
これはアウトだ。
サブクラス(Dog_pv02)で
super.name を参照している。
//Dog_pv02.java
public class Dog_pv02 extends Animal_pv01{
public Dog_pv02(String name){
super(name);
}
@Override
public void printName(){
//サブクラスから super.name を参照
System.out.println(name + "だワン!"); //super.name
}
}
Dog_pv02 の printName() で
super.name を参照してるのね。
//Driver_pv02NG.java
public class Driver_pv02NG{
public static void main(String[] args){
Dog_pv02 dog02 = new Dog_pv02("白いお父さん");
dog02.printName();
}
}
Animal_pv01クラス、
Dog_pv02クラス、
Driver_pv02NGクラス、を
wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_pv02NG.java
.\Dog_pv02.java:9: エラー: nameはAnimal_pv01でprivateアクセスされます
System.out.println(name + "だワン!"); //super.name
^
エラー1個
Dog_pv02.printNameメソッドに記述されている name は、super.nameです。
(Dog_pv02クラスに name変数の宣言が無いため、継承された super.name を示す)
private なので、サブクラスからのアクセスはできません。
継承元のクラスでは、
とりあえず
protectedを使えばいいんすね。
えっと、
そんな感じです。
お疲れ様でした。