【本サイトではGoogleアドセンス、または、アフィリエイト広告を利用しています。】
オーバーロードとは?
Javaには、メソッドをオーバーライドする他にも、
オーバーロードという方法があります。
名前が似ているので混同されがちです。
さらに書き方も似ているので、しばらくすると、
あれ?どっちだったかな。。
なんてことになりがちです!
でも、正直なところ名前なんてどうでもいいことです。
ここで使い方やメリットをしっかりマスターしましょう!
オーバーロードとは、メソッドの派生版を作ることです。
派生版とはつまり、系統は同じだけど、別の動きをするメソッドです。
系統が同じかどうか、それは、名前が同じということです。
同じ名前で別の処理を実行したい時に使います。
例えば、足し算をするこんなメソッドがあったとして、
public int add(int a, int b) {
return a + b;
}
値を3つ足す必要が出てきた時、
新しくメソッドを作るとなると名前に困りませんか?
addThreeValue?addNew?
ちょっと微妙ですよね。できればシンプルに「add」のまま使いたいです。
でも、「add」メソッドを直接書き換えたら、
メソッドを呼び出しているすべてのクラスを修正しないといけなくなります。
そして、今まで通り2つの値だけ足したい時ももちろんあるはずなので、
中の処理をどう書き換えれば良いのか迷います。
こんな時に、オーバーロードが役に立ちます!
オーバーロードとオーバーライドの違い
オーバーロードとオーバーライド、名前が似ていますが、
どう違うのかここで整理してみましょう。
【違い①】
オーバーロードは、メソッドの派生版です。
オーバーライドは、メソッドの継承版です。
【違い②】
オーバーロードは、メソッドに依存する構文です。
オーバーライドは、クラスに依存する構文です。
【違い③】
オーバーロードは、元のメソッドと引数や戻り値が異なります。
オーバーライドは、元のメソッドと引数や戻り値が同じです。
いかがでしょうか?
大きな違いとして、継承がカギになってきます。
オーバーロードには継承は関係しません。
自分のクラス内でいくつもオーバーロードして完結できます。
対して、オーバーライドはスーパークラスから引き継いで
サブクラスで定義するものです。
つまり、オーバーロードは追加、オーバーライドは上書き、
という考え方の違いが出てきます。
オーバーライドについては、以下でも説明していますので
あわせて読んでみてください!
では、今からオーバーロードの条件など見ていきましょう!
オーバーロードできる対象と条件
オーバーロードは以下の構文に適用できます。
・メソッド
・コンストラクタ
ちなみに、コンストラクタもメソッドの1種になります。
クラスをインスタンス化する時に呼び出されるメソッドがコンストラクタです。
また、オーバーロードとして扱われる為の条件は以下になります。
・名前が同じであること
・引数が異なること
一致しない条件が1つでもあると、重複定義としてエラーになるか、
エラーが出ない場合は、別のメソッドという扱いになります。
また、戻り値の型を変えることもできますが、
名前も引数も同じで、戻り値の型のみ違うメソッドは定義できません。
オーバーロードの使い方(サンプルコード)
では、サンプルコードで使い方を見ていきましょう。
まずは、オーバーロードする前の状態です。
これは、本サイトでおなじみになってきた、ロボット君のクラスです。
なんとロボット君は自己紹介ができます!ヨロシク!
package example;
// クラス:ロボット
public class Robot {
// フィールド:エネルギー
public int energy;
// コンストラクタ
public Robot(int energy) {
this.energy = energy;
}
// メソッド:自己紹介
public void selfIntroduction() {
System.out.println("ロボット君デス!ヨロシク!");
}
}
ロボット君を動かす為のメインクラスです。
package example;
// クラス:メイン処理実行用
public class Example {
// メイン処理
public static void main(String[] args) {
// ロボット
Robot robot = new Robot(100);
// 自己紹介
robot.selfIntroduction();
}
}
実行結果は以下です。
ロボット君デス!ヨロシク!
では、ここでロボット君2号を作成したらどうなるでしょう?
package example;
// クラス:メイン処理実行用
public class Example {
// メイン処理
public static void main(String[] args) {
// ロボット
Robot robot = new Robot(100);
// 自己紹介
robot.selfIntroduction();
// ロボット2号
Robot robot2 = new Robot(100);
// 自己紹介
robot2.selfIntroduction();
}
}
実行結果はこうなります。
ロボット君デス!ヨロシク!
ロボット君デス!ヨロシク!
ど、どっちがどっちかわからない!
ということで、Robotクラスを改修して名前を付けるようにしましょう。
でも、条件があります。
最初のロボット君はもうすでに完成して動作確認も済ませているので、
ロボット1号作成のプログラムはなるべく触らないようにしたいです。
よし!オーバーロードを使って解決しましょう!
改修方法は2通りあります。
メソッドのオーバーロード
まずは、メソッドをオーバーロードする方法です。
ロボット君が持つ自己紹介メソッドをオーバーロードして、
名前を引数で指定できる派生版を作成してみました。
さらに、もともとあったメソッド内の処理は、
オーバーロードしたメソッドを呼び出すように書き換えて、
似たような処理が同じクラスで増殖しないように配慮しました。
package example;
// クラス:ロボット
public class Robot {
// フィールド:エネルギー
public int energy;
// コンストラクタ
public Robot(int energy) {
this.energy = energy;
}
// メソッド:自己紹介
public void selfIntroduction() {
// 名前の指定がない時は「ロボット君」で固定
selfIntroduction("ロボット君");
}
// メソッド:自己紹介(オーバーロード)
public void selfIntroduction(String name) {
System.out.println(name + "デス!ヨロシク!");
}
}
メインクラスです。2号の自己紹介メソッドだけ書き換えました。
package example;
// クラス:メイン処理実行用
public class Example {
// メイン処理
public static void main(String[] args) {
// ロボット
Robot robot = new Robot(100);
// 自己紹介
robot.selfIntroduction();
// ロボット2号
Robot robot2 = new Robot(100);
// 自己紹介
robot2.selfIntroduction("ロボット君2号");
}
}
実行結果は以下です!
ロボット君デス!ヨロシク!
ロボット君2号デス!ヨロシク!
これで1号と2号の区別がつきますね!
メインクラスはほとんど触らずに改修できました。
コンストラクタのオーバーロード
次に、コンストラクタのオーバーロードを使う方法です。
今度は、ロボット君にフィールド「名前」を追加して、
インスタンス作成時にコンストラクタで指定できる派生版を作成しました。
それにあわせて、自己紹介では名前フィールドを使うようにして、
元々のコンストラクタには、1号君の名前を固定で入れるように設定しました。
package example;
// クラス:ロボット
public class Robot {
// フィールド:エネルギー
public int energy;
// フィールド:名前
public String name;
// コンストラクタ
public Robot(int energy) {
this.energy = energy;
// 名前の指定がない時は「ロボット君」で固定
this.name = "ロボット君";
}
// コンストラクタ(オーバーロード)
public Robot(int energy, String name) {
this.energy = energy;
this.name = name;
}
// メソッド:自己紹介
public void selfIntroduction() {
System.out.println(this.name + "デス!ヨロシク!");
}
}
メインクラスです。
ロボット君2号を作る時のコンストラクタのみ書き換えました。
package example;
// クラス:メイン処理実行用
public class Example {
// メイン処理
public static void main(String[] args) {
// ロボット
Robot robot = new Robot(100);
// 自己紹介
robot.selfIntroduction();
// ロボット2号
Robot robot2 = new Robot(100, "ロボット君2号");
// 自己紹介
robot2.selfIntroduction();
}
}
実行結果は以下です。
ロボット君デス!ヨロシク!
ロボット君2号デス!ヨロシク!
こちらもうまくいきました!
同じように、メインクラスにはほとんど影響が出ていないのがポイントです!
オーバーロードを使うメリット
サンプルコードを見てもらったことで、
オーバーロードのメリットは何となく伝わったかと思いますが、
ここで改めて整理しておきましょう!
・メソッドの処理を拡張したい時に同じ名前が使えるので、呼び出す時に迷わない。
(コーディングミスの防止。可読性が上がる。)
・オーバーロード元のメソッドを呼び出しているプログラムを書き換える必要がない。
(現状のプログラムに大きな影響を出さずに改修できる。)
オーバーロードは、プログラムのファイル数が多い、
または、複数人で開発をしているような時に大きく効果を発揮します。
また、新規にクラスを作るタイミングではなく、
後付けで拡張したい時などに作ることが多いです。
オーバーロード まとめ
Javaのオーバーロードについて以下説明しました。
・オーバーロードについて
・オーバーロードとオーバーライドの違い
・オーバーロードの対象と条件
・メソッド、コンストラクタのオーバーロード(使い方)
・オーバーロードを使うメリット
他にも使い方によって様々なメリットが生み出せるはずなので、
特徴をしっかり覚えておいて、いつでも使えるようにしておきましょう!