はじめに
この章では、javaの便利な機能について学びましょう。 現場で必ず使う機能になるかと思います。
とっても便利なので使いまくりです。
基礎となる処理を呼び出したり、それに上書きできたりする機能です。
まずは触れてみて、理解を深めていきましょう!
Step1: オーバーロード
引数の型や数が異なる同名のメソッド又はコンストラクタを複数記述することです。
呼び出す場合は、 引数の型や引数の数が同等なメソッド又はコンストラクタが呼ばれ処理を行います。
こんなややこしいものが必要な理由は一つ、便利だからです!
利用者の入口 (メソッド名)は同じだけど、引数によって最終的な処理結果を変更したり、
処理結果にバリエーション持たせたりすることが可能です!
オーバーロード : メソッド
オーバーロード:コンストラクタ
補足
・デフォルトコンストラクタ
通常コンストラクタは、そのクラス内に何も記述しなければデフォルトコンストラクタが用意されます。
(※コード上にはないが、実処理(new クラス名)のタイミングで空のコンストラクタ (public Sum() { })を呼び出している状態となります。)
・オーバーロードを活かしたコンストラクタ
冗長な記述を減らし、可読性の高い初期化処理の実現に役立ちます。
しかし、以下の場合はコンパイル時点でエラー (再帰的コンストラクター)を吐いてしまい、思ったような処理を実現することができません。
【サンプル: コンストラクタ内で自クラスのコンストラクタを呼び出す】
エラーの原因は、自分自身のコンストラクタ (③) を呼び出すことによる処理の終結が無いことです!
①、②は③を呼び出し、③は③を呼び出します。
①、②は結局③に行き着くため、③のコンストラクタを読んだ状態と同じになります。
これでは、永遠にコンストラクタの処理が終わりませんよね?
そのため、3つのコンストラクタ内で共通で使用できるメソッド(constructor() ) を用意し、 一つの口で初期化できるようにしている訳です!
※「再帰」というのは、端的に言えば、 自分自身を呼び出すことを意味します。
Javaだけでなく、多言語で使用されるテクニックですが、ここでは紹介程度にしておきます。
練習問題
下記に示すプログラムを作成し、実行しましょう。
実行前にどのコンストラクタが呼び出されるか考えてみましょう。 (こちらはSlackで報告などなくて大丈夫です。)
実行結果をスクリーンショットを撮ってSlackで提出してください。 ※コピペは禁止です。
Sum クラス
SumMain クラス
Step2: 継承
継承とは、任意のクラスを他のクラスで受け継ぐことです。
任意の元のクラスをスーパークラス、受け継ぐクラスをサブクラスと呼びます。
継承することによってスーパークラスの持ち物であるフィールドやメソッドがサブクラスで使用することが可能となります。
ただし、スーパークラスのフィールドやメソッドのアクセス修飾子が private の場合継承してもサブクラスで使用することはできませんので注意してください。
private 以外の場合、サブクラスで使用することが可能です。
Step3: 継承の方法
継承するには、 extends を記述します。 extendsとは、拡張するという意味です。
クラスの宣言文は、「クラス xxx は、スーパークラス SSSを拡張する」 といった感じで読むことができます。
ただし、継承できるクラスは1つのみです。複数のクラスを同時に継承したりすることはできません。
継承のメリット
- 同じような機能をもつ重複したコードを書かないようになるので、コードの再利用性が高くなる
- メソッドを追加したり、オーバライド (上書き) することができるので自由に拡張する
重複したコードを書くと勘違いやミスが増え思わぬバグやトラブルを起こしてしまう可能性があり、メンテンスが難しくなります。
メンテナンスが難しくなることによって、「機能の追加」 や 「改善」 が難しくなり拡張性が下がってしまいます。
効率よく少ないコードでプログラミングしないと、 開発がどんどん難しくなりコードを書くプログラマーも苦しくなってきてしまいます。
継承を用いる場合は、「骨組み」 となるクラスを1つ作り、その1つのクラスを継承するのが一般的です。
具体例では、「RPGのキャラクター」 があります。
初期のキャラクターをスーパークラスとして、継承して戦士クラスとか魔法使いクラスなどを作るイメージです。
そうすることで、 戦士であれば剣を使う部分だけ、魔法使いであれば魔法を使う部分だけ、 つまり必要最低限のコードを 追加するだけでプログラミングができてしまうのです。
Step4: オーバーライド
オーバーライドとは、継承関係においてスーパークラスのメソッドの処理をサブクラスの同名のメソッドで上書きすることです。承関係以外ではこの現象は起こりませんが、 継承するサブクラスを作成するときは多少スーパークラスのことを知らないと意図せずオーバーライドしてしまうことがありますので注意してください。
サンプル: オーバライドその1
Greet クラス
GreetInJapaneseクラス
GreetMain クラス
【出力結果】
・morning メソッドを継承先クラスである GreetInJapanese で上書き
継承先のクラスにてスーパークラスの持つメソッドの処理を上書いています。
Good Morning を表示したければ、下記のようにします。
サンプル:オーバライドその2
・super キーワードを指定してのmorning() メソッドの呼び出し
こうすることでスーパークラスであるGreetクラスの morning() メソッドが呼び出されます。
オーバーライドの利用例として、特定のサブクラスにおいて、当該メソッドの処理内容を修正・変更するという利用例があります。
【例:既存クラスのメソッドの処理内容を変更したい場面】
このとき、そのスーパークラスのメソッドの処理内容を直接修正することが可能だったとします。
(※今回の場合は、morning() の System.out.println(“Good Morning”); 部分を指します。)
しかし、他のクラスでもそのクラスのメソッドを使っている可能性は否めません。
そのため、そのメソッドを修正したことによって他のクラスに影響が出る可能性があります。
上記サンプルの Greet で言えば、
GreetInJapanese 以外のオーバーライド先の処理内容として、良い朝ですね! などと出力するようにしている場合です。
そのような場合は、スーパークラスのメソッドを直接修正せず、クラスを継承したサブクラスを用意して当該メソッドをオーバーライドし、処理内容を修正 (上書き) することで修正内容をサブクラスのみに適用することができます!
つまり、
- プログラムの影響範囲を限定する
- コードを再利用する
という2点に重きを置いた実装方法になります。
大本は変えず、使用先のみに修正や変更を加えよう! ということです。
RPGの例で考えよう
具体的な使い方について触れていきます!
継承したサブクラスでは、 スーパークラスのメソッドを使うことができます。
新しく追加して機能を追加することもできますが、 実はスーパークラスのメソッドを 「上書き」 することもできます。
スーパークラスのメソッドをサブクラスで上書きすることを「オーバーライド」といいます。
このオーバーライドが継承を使う上でもっとも重要な機能となります。
具体例としては、
・RPGのキャラクターが行う特定のアクションを上書きする場合
オーバーライドはRPGのキャラクターが行う特定のアクションを上書きする場合によく使います。
攻撃する処理を書いたメソッド (attack () ) をオーバーライドし、
「忍者は通常攻撃で一定確率で即死攻撃」
「白魔道士は攻撃で回復を行う」
といった具合で上書きするようなイメージです。
これも上記のように「一定確率で即死」 「回復する」 などの違う部分だけをプログラミングするだけで済みますし、同じメソッドを使っても実行するクラスによって違う動作を行うようにできます。
こちらの方が効率よくプログラミングすることができますね!
課題
Java中級からはEclipseでの課題対応となります。
2-9のフォルダの中にプロジェクトがありますので、インポートして以下の画像のように出力されるようにコーディングしなさい。
※Plus.javaのオーバーロードしているplusメソッドを3つを呼び出して、それぞれに適当な引数を与えて表示させてください。
