継承
クラスの進化
オブジェクト指向プログラム、OOPの基本であるクラスの概念はわかってくれたと思います
さらにオブジェクト指向プログラムがこれだけ世に反映する理由が、これから学ぶ「継承」で理解できるでしょう
継承は、オブジェクト指向プログラムの主要三概念の一つです
継承はいわばクラスの進化です
私たちがこれから作りたい目標に、非常に近い理想のクラスが存在するとします
あとは、そのクラスに少しだけメンバを付け足す程度でよさそうです
なのに、もう一度最初から似たようなクラスを何度も作りなおすのは合理的ではありません
継承は、そのようなクラスの機能をそのまま引き継ぐことができるのです
継承元となるクラスをスーパークラスと呼びます
そして、このスーパークラスの機能を利用する新しいクラスをサブクラスと呼びます
サブクラスには最初からスーパークラスのメンバが登録されています
継承しただけで、スーパークラスのメンバを再利用することができるのです
クラスを継承するにはextendsキーワードを使用します
class sub_class extends super_class
sub_classにはスーパークラスからメンバを引き継ぐサブクラスを指定します
super_classはサブクラスに継承させるスーパークラスを指定します
継承できるのは一つのスーパークラスだけです
class super_class {
String name;
}
class sub_class extends super_class {
int age;
void write() {
System.out.println(this.name + "\t" + this.age);
}
}
class test {
public static void main(String args[]) {
super_class naru = new super_class();
sub_class sinobu = new sub_class();
naru.name = "成瀬川なる";
sinobu.name = "前原しのぶ";
sinobu.age = 13;
System.out.println("名前\t\t年齢");
System.out.println(naru.name);
sinobu.write();
}
}
super_classのメンバはString型変数 name しかありません
super_class型の変数 naru はsuper_classのオブジェクトを参照しているので、メンバはそれだけです
しかし、sub_classはsuper_classを継承しています
sub_classの sinobu はスーパークラスのnameメンバと自分のメンバを利用することができます
こうして、sub_classはsuper_classを拡張しているのです
データの隠蔽
ここで、Java言語学習者が気にしなければならないのが「名前の衝突」です
スーパークラスとサブクラスに同名の変数やシグネチャの同じメソッドが存在しているとどうなるのでしょう?
class super_class {
String name = "成瀬川なる";
}
class sub_class extends super_class {
String name = "前原しのぶ";
}
class test {
public static void main(String args[]) {
sub_class obj = new sub_class();
System.out.println(obj.name);
}
}
このプログラムは問題なくコンパイルすることができます
objが参照しているメンバ変数 name はサブクラスのものなのか、スーパークラスのものなのかわかりませんね
実は、このような場合はスーパークラスのメンバが隠蔽されます
つまり、名前が衝突した場合は自分のクラスのメンバが最優先されます
これは、メンバ変数だけではなく、メソッドでも同じことが起こります
隠蔽されたスーパークラスのデータを参照するにはsuperキーワードを使用します
super.member;
super.member(args);
上はメンバ変数のアクセス時の書式です。memberには参照するメンバ変数名を指定します
下はメソッドの場合です。memberにはメソッド名をargsにはパラメータを指定します
class super_class {
String name = "成瀬川なる";
}
class sub_class extends super_class {
String name = "前原しのぶ";
void write() {
System.out.println(super.name);
System.out.println(this.name);
}
}
class test {
public static void main(String args[]) {
sub_class obj = new sub_class();
obj.write();
}
}
obj.write()が実行されると、println()メソッドから super.name とスーパークラスのメンバを呼び出してます
これらは、インスタンスメンバだけでなく静的メンバでも同様です
次のプログラムは、スーパークラスに隠されたメソッドを呼び出すサンプルです
class super_class {
void write(String str) {
System.out.println("super_class");
System.out.println(str);
}
}
class sub_class extends super_class {
void write(String str) {
System.out.print("sub_class->");
super.write(str);
}
}
class test {
public static void main(String args[]) {
sub_class obj = new sub_class();
obj.write("kitty on your lap");
}
}
ただし、C言語の構造体のネストのような super.super.member という記述はできません
参照できるのは、ひとつ上のスーパークラスまでです
extends
クラスの宣言で使用します
作成されるクラスのスーパークラスを指定します
super
スーパークラスの隠蔽された変数や、メソッドにアクセスするために使用します