#はじめに
この記事は備忘録である。
参考書レベルの内容だが、本記事に掲載するコードについては、
間違えたものが中心となる。これは実際にコーディング中に間違えた部分を掲載し、自分で反省するために投稿するという目的によるもの。
また、後日にJavaSilver試験問題の勉強を兼ねて復習するため、深い部分の話はここでは触れない。
##環境
言語:Java11、JDK13.0.2
動作環境:Windows10
#オーバーライド
前回でスーパークラスとサブクラスの関係は扱った。
サブクラスにはスーパークラスのメソッドが継承されているが、同じメソッド名を使いながら別の処理を定義したいということがある。
例えばshow〇〇()
でメンバをチェックするためのメソッドを用意する場合。同じチェックするにしてもwatch〇〇(),see〇〇(),check〇〇()
と使い分けを作ることはできるだろう。だが、引数や型がそれぞれ違うとなれば覚えて使うのが非常に困難になるし、それだけコードが無駄に長くなれば可読性も落ちる。
サブクラスには、スーパークラスで実装されたものと全く同じメソッドを新たに定義することができ、オブジェクトから呼び出す場合サブクラスの方が優先される。
条件としては、
1.シグニチャ(メソッド名、引数リストの型、数、順番)が同じ
2.アクセス修飾子が同じかより緩い
3.戻り値の型が原則同じ(共変戻り値を除く)
サブクラスのメソッドが、スーパークラスのメンバに代わって機能することを**オーバーライド(overriding)**と呼ぶ。
##スーパークラスでまとめて扱う
何度も書くが、サブクラスにはスーパークラスのメンバが継承されている。そしてオーバーライドでサブクラス専用の処理を書いて優先的に機能させることが出来る。
よって、同じスーパークラスの子であるサブクラスを使う際、スーパークラスのメソッドで一括して処理を記述することが出来る。
class WildCat
{
protected int number;
protected double weight;
public WildCat()
{
number = 1;
weight = 1.0;
}
public void getCat(int n,double w)
{
number = n;
weight = w;
System.out.println(number +"番目の猫の体重は" + weight + "kgです。");
}
public void show()
{
System.out.println("この猫は" + number + "番目の猫です。");
System.out.println("この猫の体重は" + weight + "kgです。");
}
}
このWildCat
クラスをもとに、HouseCat
とMyCat
のクラスを用意する。
class HouseCat extends WildCat
{
public void show()
{
System.out.println("このイエネコは" + number + "番目です。" );
}
}
class MyCat extends WildCat
{
public void show()
{
System.out.println("このうちの猫は" + number + "匹目で、今の体重は" + weight + "でした。" );
}
}
そのうえで、個別の猫を用意する。
class arrayCatsShow
{
public static void main(String[] args)
{
WildCat[] cats = new WildCat[4];
cats[0] = new WildCat();
cats[0].getCat(1, 5.2);
cats[1] = new HouseCat();
cats[1].getCat(2, 4.2);
cats[2] = new MyCat();
cats[2].getCat(3, 5.6);
cats[3] = new MyCat();
cats[3].getCat(4, 8.4);
for(int i=0; i< cats.length; i++){
cats[i].show();
}
}
}
スーパークラスの配列を用意してから個別にnew
したので、それぞれのshow()
定義に基づいた文章が現れる。
##付け足しだけしたいとき
スーパークラスの処理+サブクラスの処理 にしたい場合。
class HouseCat extends WildCat
{
public void show()
{
super.show();
System.out.println("このイエネコは" + number + "番目です。" );
}
}
super.メソッド名
でスーパークラスの処理をそのまま持ってこれるので、あらためてすべて書く必要はない。これはフィールドにも言えることなので、super.フィールド
でスーパークラスの値を持ってくることもできる。
ところで、スーパークラスのメソッドをオーバーライドされたくないときは、public final void show()
のように**final
をつければオーバーライドできなくなる**。
これはクラス名とフィールドでもできるので、finalクラス
ならサブクラスの拡張不可になり、finalフィールド
なら**フィールドの値が宣言時の初期化を除いて変更されない定数(constant)
**になる。
#おわりに
共変戻り値という言葉をSilver問題集から見つけたが、近いうちにクラスライブラリを調べるつもりなので、そこでクラス間の関係をはっきりさせてから扱いたい。
#参考
出来るだけ自分で変数や式を書いてコンパイルしているので、完全に引用する場合はその旨記述する。