こんにちは!フリーランスの長野です。
Javaには同じメソッド名で引数の型や数が違うメソッドを2つ以上定義できるオーバーロードがあります。
この記事では、オーバーロードについて
・オーバーロードとは
・オーバーロードの使い道(使うメリット)
・オーバーライドとの違い
・オーバーロードの使い方
といった基本的な内容から
・引数が継承関係にあるときの優先順位
・コンストラクタのオーバーロード
など応用的な内容についても解説していきます。
今回はオーバーロードについて、使い方をわかりやすく解説します!
なお、Javaの記事については、こちらにまとめています。
オーバーロードとは
オーバーロードとは、同じクラスの中でメソッド名と戻り値の型が同じで、引数の型や数、並び順が違うメソッドを2つ以上定義することをいいます。
オーバーロードの使い道(使うメリット)
同じような処理だけれども、一部を変数にして処理結果をより自由に変えたい場合などで使うと便利です。
オーバーライドとの違い
似たような用語でオーバーライドがあります。
よく間違われるので、簡単に説明しておきます。
オーバーライドは、継承した子クラスで親クラスと同じメソッド名のまま、処理内容を変更して再定義することを言います。
引数の型や数、並び順は親クラスのそれと同じでなければなりません。
今回お伝えしているオーバーロードは、同じクラスの中でメソッド名と戻り値の型が同じで、引数の型や数、並び順が違うメソッドを定義することでした。
間違えないようにしましょう!
ちなみにオーバーライドについてはこちらで詳しく解説していますので、参考にしてください。
また、オーバーライドをするときには「@Override」というアノテーションをつけてオーバーライドしていることを明示します。
アノテーションの使い方についてはこちらの記事で詳しく解説しているので、ぜひ確認してください。
オーバーロードの使い方
オーバーロードの使い方についてサンプルコードで確認しましょう。
public class Main { public static void main(String args[]) { msg("佐藤"); msg("山田", "はじめまして"); } static void msg(String name) { System.out.println("こんにちは、" + name + "です"); } static void msg(String name, String greeting) { System.out.println(greeting + "、" + name + "です"); } }
実行結果:
こんにちは、佐藤です はじめまして、山田です
このサンプルコードでは、同じメソッド名で引数の数が違う2つのメソッドmsgを実行しています。
メソッドを呼び出して引数を指定する際にString型の変数を1つ指定すれば、String型の引数を1つ持つメソッドが呼び出されて実行されています。
また、String型の変数を2つ指定すればString型の引数を2つ持つメソッドが呼び出されて実行されています。
このように、同じメソッド名の中からどのメソッドを呼び出すかは、指定する引数の型や数、順番を元にコンパイラーが判断してくれるようになっています。
オーバーロードができない場合
オーバーロードをするためには決まりごとがあります。
オーバーロードは、引数の型と個数と全く同じでは使えません。
これはメソッド名と引数が全く同じだと、どちらのメソッドを使えばいいのか判断できなくなるためです。
そのため、オーバーロードをするときには必ず引数の「型」と「数」と「並び順」を変えて定義するようにしてください。
注意点として、戻り値の方を変えれば異なるメソッドと判断されるのではないかと思うかもしれませんが、引数が同じ場合には使用できません。
オーバーロードをするときには必ず引数の型と数と並び順を変えるようにしてください。
引数が継承関係にあるときの優先順位
引数の数や順番が同じで、型だけが違う場合に注意しなければならないことがあります。
型に継承関係がある場合は、どのメソッドが呼び出されるか優先順位が決められています。
サンプルコードで確認しましょう。
public class Main { public static void main(String args[]) { Integer i = new Integer(1); Number num = i; // アップキャスト msg(num); } static void msg(Integer i) { System.out.println("引数がInteger型のメソッドを呼び出しました"); } static void msg(Number n) { System.out.println("引数がNumber型のメソッドを呼び出しました"); } }
実行結果:
引数がNumber型のメソッドを呼び出しました
このサンプルコードでは、Integer型のオブジェクトiをNumber型のオブジェクトnumに格納しています。
IntegerクラスはNumberクラスを継承したクラスなので、このように格納することが可能です。
これをアップキャストといいます。
このような場合も実行結果のとおり、指定する引数の型にあわせてメソッドが呼び出されます。
生成したインスタンスの型ではないので注意しましょう。
なおアップキャストについては、こちらで詳しく解説していますので、ぜひ参考にしてください。
コンストラクタのオーバーロード
これまではメソッドのオーバーロードについてお伝えしてきました。
コンストラクタでもメソッドと同じようにオーバーロードで定義することが可能です。
サンプルコードで確認しましょう。
class MyClass { public MyClass() { } public MyClass(String name) { System.out.println("こんにちは、" + name + "です"); } public MyClass(String name, String greeting) { System.out.println(greeting + "、" + name + "です"); } } public class Main { public static void main(String args[]) { MyClass mc1 = new MyClass("佐藤"); MyClass mc2 = new MyClass("山田", "はじめまして"); } }
実行結果:
こんにちは、佐藤です はじめまして、山田です
このサンプルコードでは、MyClassクラスで引数なしのコンストラクタとString型の引数を1つ持つコンストラクタとString型の引数を2つ持つコンストラクタを定義しています。
MyClassクラスのインスタンスを生成する際に、引数の数によって呼び出されるコンストラクタが違うのがわかります。
まとめ
いかがでしたか?
今回はオーバーロードについて解説しました。
オーバーライドとの違い、引数の優先順位には注意して下さい。
使いこなすことができるように、この記事を何度も参考にして下さいね!