WisdomSoft - for your serial experiences.

4.4 オーバーロード

同じスコープ内であってもパラメータの型または数が異なっていれば同じ名前のメソッドを複数宣言できます。

4.4.1 同名のメソッド

メソッド宣言のうち、メソッドの名前と仮パラメータリスト全体をシグネチャと呼びます。変数などの識別子は同じスコープ内で重複してはならないということが鉄則であり、メソッドも例外ではありませんが、メソッドは識別子ではなくシグネチャがその対象となります。つまり、クラスには同じメソッド名は許可されますが、同じシグネチャを持つメソッドが複数宣言されている場合はエラーとなるのです。

何がいいたいのかというと、プログラムを拡張する場合や、ほぼ同一の機能を提供するメソッドを宣言するとき、既存のメソッドと同名のメソッドを宣言してしまったり、または既存のメソッドと同名であることが好ましい場合があります。Java 言語はクラス内にシグネチャが衝突しない限り同名のメソッドを宣言することができるため、性質が同じメソッドは、仮パラメータリストさえ異なれば同じ名前を指定することができます。このような、同じクラスで複数のメソッドが同じ名前で異なるシグネチャとして宣言されている場合、メソッドはオーバーロードされていると表現します。

オーバーロードは、主に同じ機能を提供するメソッドで、受け取る引数にバラエティを持たせたい場合に採用します。これまで何度も使ってきた println() メソッドは、オーバーロードの代表的な例でしょう。println() メソッドは文字列以外に、数値や文字、boolean 型の値を渡すことができます。これは println() メソッドが様々な型を受けることができるように、オーバーロードされているためです。

オーバーロードされた、どのメソッドを呼び出すかという問題は、メソッドを呼び出すときに与えられた引数リストの型から判断されます。

コード1
class Test {
	public static void main(String args[]) {
		Test obj = new Test();
		obj.method();
		obj.method((char)0x732B);
		obj.method("Kitty on your lap");
		obj.method("Kitty on your lap" , 10);
	}
	void method() {
		System.out.println("引数のない method() です");
	}
	void method(char code) {
		System.out.println("code = " + code);
	}
	void method(String str) {
		System.out.println("str = " + str);
	}
	void method(String str , int iValue) {
		System.out.println("str = " + str + " , iValue = " + iValue);
	}
}
実行結果
>java Test
引数のない method() です
code = 猫
str = Kitty on your lap
str = Kitty on your lap , iValue = 10

コード1では同じ名前の method() メソッドが複数宣言されています。しかし、これらのメソッドは受け取る引数の型や数が異なるため、シグネチャが異なります。そのため、メソッドは衝突せずにオーバーロードされます。

これらのメソッドのどのメソッドを呼び出すかは、メソッドを呼び出したときに引数として渡された値の型によって決定されます。最初の method() メソッドの呼び出しには何も引数が指定されていないため、引数のない method() メソッドが呼び出されています。次に数値を char 型に変換して引数として渡しています。これは char 型を受け取る method() が呼び出されます。実行結果を見れば、それぞれ適切なメソッドが呼び出されていることが確認できます。

もちろんのことですが、実行内容が意味的にまったく関係のないメソッドをオーバーロードするべきではありません。メソッドの目的が同一で、メソッドの起動方法を分けたい時にオーバーロードを利用します。

コード2
class Color {
	int r , g , b;
	void setColor(float r , float g , float b) {
		this.r = (int)(0xFF * r);
		this.g = (int)(0xFF * g);
		this.b = (int)(0xFF * b);
	}
	void setColor(int color) {
		r = (color & 0xFF0000) >>> 16;
		g = (color & 0x00FF00) >>> 8;
		b = (color & 0x0000FF);
	}
	void showColor() {
		System.out.println("R = " + r + " : G = " + g + " : B = " + b);
	}
}

class Test {
	public static void main(String args[]) {
		Color color = new Color();
		color.setColor(1.0F , 0.5F , 0.628F);
		color.showColor();
		color.setColor(0xAAFF38);
		color.showColor();
	}
}
実行結果
>java Test
R = 255 : G = 127 : B = 160
R = 170 : G = 255 : B = 56

コード2の Color クラスでは、同一名のメソッド SetColor() が 2 つ宣言されています。これらのメソッドは名前が衝突していますが、シグネチャが異なっているためオーバーロードされています。色の表現は RGB 要素をそれぞれ 1 バイトで表すシステムもあれば、0.0 ~ 1.0 までのパーセントで表すシステムも存在します。そこで、様々な型で色を設定することができるようにオーバーロードを利用するという方法が考えられるでしょう。このプログラムは、それぞれの型に対応したメソッドを作成することによって、同時にこれを解決しています。