java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

メソッドのオーバーロードの使い道

投稿日:

最終更新日:2022年05月01日

アイキャッチ

こんにちは。今回はJavaについて、メソッドのオーバーロードという機能を使う練習をしました。

Javaでは、同じ名前のメソッドでも次の違いがあれば定義できます。

  1. 引数の型が異なる。
  2. 引数の数が異なる。

これはメソッドのオーバーロードと呼ばれます。

今回は上記の2つのパターンそれぞれを使ったサンプルを作ってみました。サンプルを2つ載せました。また、それぞれの前に、標準APIでオーバーロードが利用されている例を挙げました。

標準APIでオーバーロードが使われている例1

java.io.PrintStreamクラスにprintln()がいくつか定義されています。これらはコンソールに文字列等を出力するメソッドです。

println()の使用例

System.out.println("Hello World."); // (1)
System.out.println();               // (2)
System.out.println(1234);           // (3)

結果

Hello World.

1234

(1)で使っているのは「void println​(String x)」です。引数に指定された文字列がコンソールに出力されます。また、行を終了します。

(2)で使っているのは「void println()」です。改行のみ出力します。

(3)で使っているのは「void println​(int x)」です。整数が出力されます。また、行を終了します。

同じ名前のメソッドでも、(1)と(2)のように引数のが異なる同名のメソッドを定義することが出来ます。また、(2)と(3)のように引数のが異なる同名のメソッドを定義することが出来ます。

EclipseではPrintStreamクラスのソースコードを閲覧することが出来ました。上記のメソッドは以下のように定義が記述されていました。

PrintStreamクラスのソース抜粋

    ...

    public void println(String x) {
        ...
    }

    public void println(int x) {
        ...
    }

    public void println() {
        newLine();
    }

このようにオーバーロードという機能により、引数の型が異なるか引数の数が異なるような同じ名前のメソッドが定義できます。

オーバーロードのサンプル1:引数の型を変えたメソッドを定義

例えば、整数と小数を扱っているプログラムで出力を以下のように揃えたいとします。

出力
int 「***.0」というように出力させる。
double 小数点以下第2位を四捨五入して、「***.1」というように出力させる。

(上記表に記載した型は一部のプリミティブ型だけですが、他の型は考えないことにします。)

上記目的のために、int型とdouble型の変数それぞれを目的の文字列に変換するメソッドを実装するということを考えます。

変数の型に応じて処理を記述したいのですが、if文は難しそうです。そこで、メソッドのオーバーロードを利用して次の2つのメソッドを定義します。

  1. public String getMyString(int value)
  2. public String getMyString(double value)

1番目のメソッドは引数がintなので、上記表のint型に対する出力内容の文字列を返却するように実装します。2番目も同様にdouble型に対して文字列を返却するように実装します。

オーバーロードの使用例1

public class Sample001 {

	public static void main(String[] args) {
		Sample001 sample001 = new Sample001();
		sample001.test();
	}

	public void test() {
		String s = null;

		// 整数を使う
		int value1 = 123;
		s = getMyString(value1);
		System.out.println(s);

		// 小数を使う
		double value2 = 456.789;
		s = getMyString(value2);
		System.out.println(s);
	}

	public String getMyString(int value) {
		// (1)
		return String.valueOf(value) + ".0";
	}

	public String getMyString(double value) {
		// (2)
		double round_value = (double)Math.round(value * 10) / 10;
		return String.valueOf(round_value);
	}

}

結果

123.0
456.8

(1)はint型に対する処理です。StringクラスのvalueOf()メソッドで整数を文字列に変換しています。文字列結合で小数点以下の表示を追加しています。(正確にはString java.lang.String.valueOf(int i)を使用。)

(2)はdouble型に対する処理です。Mathクラスのround()メソッド引数に小数点以下第1位を四捨五入してくれます。今回は10掛けた数値をこのメソッドで変換して10で割ることで、小数点以下第2位を四捨五入した値を取得しています。StringクラスのvalueOf()メソッドで小数を文字列に変換しています。(正確にはString java.lang.String.valueOf(double d)を使用。)

標準APIでオーバーロードが使われている例2

Stringクラスには、部分文字列を取得するためのsubstring()メソッドがあります。オーバーロードにより以下の2つがあります。

public String substring(int beginIndex, int endIndex)
指定されたbeginIndexから始まり、インデックスendIndex – 1にある文字までを返却。
public String substring(int beginIndex)
指定されたインデックスで始まり、この文字列の最後までを返却。

2番目のメソッドの定義は1番目のメソッドの引数を減らしたものです。2番目は1番目の特別な場合になっています。

オーバーロードのサンプル2:引数の数を変えたメソッドを定義

上記のようなオーバーロードの使い方の例として、単価と数量の配列と税率から税込み価格を計算するメソッドを作るとします。

今回は以下のようなサンプルを作りました。

ソース

public class MyPrice {

	/**
	 * @param unit_cost_array 単価の配列
	 * @param count_array 個数の配列
	 * @param tax 税率
	 * @return 単価 * 個数 * (1 + 税率)の合計を返却する。
	 */
	public static int calcPrice(int[] unit_cost_array, int[] count_array, double tax) {
		// (1)
		int total = 0;
		for (int i = 0; i < unit_cost_array.length; i++) {
			int price = (int)(unit_cost_array[i] * (1 + tax)) * count_array[i];
			total += price;
		}

		return total;
	}

	/**
	 * @param unit_cost_array 単価の配列
	 * @param count_array 個数の配列
	 * @return 単価 * 個数の合計を返却する。
	 */
	public static int calcPrice(int[] unit_cost_array, int[] count_array) {
		// (2)
		return calcPrice(unit_cost_array, count_array, 0.0);
	}

}

最初のcalcPrice()メソッドは引数を3つ定義しています。単価の配列と個数の配列から税込み価格の合計を返却するメソッドです。2番目のメソッドは1番目のメソッドの第3引数がないバージョンです。

引数 1番目のメソッド 2番目のメソッド
unit_cost_array あり あり
count_array あり あり
tax あり なし

(1)では配列の要素番号ごとに掛け算して合計するという計算をしています。

上記の特別な場合として、税率が0の場合が考えられます。この場合を2番目のcalcPrice()メソッドで取得できるように定義しています。

(2)では1番目のcalcPrice()を呼び出しています。第3引数に0.0を直接設定しています。なお、オーバーロードを実装する際に、誤ってそのメソッド自身を呼び出すように記述してしまうと無限ループになってしまうので、注意が必要です。

上記2つのサンプルのように以下のようにオーバーロードを利用することが出来ます。

  • 引数の型を変えた同名のメソッドを定義する
  • 引数の数を変えた同名のメソッドを定義する

以上、参考になれば幸いです。