C 言語では、同じ名前の関数を同一のスコープ上に宣言することはできませんでした。 しかし、D 言語は関数の名前だけではなく、関数の戻り値と引数も含めた全体を識別に利用するため、関数の名前だけが衝突することは問題にはなりません。 この、関数の戻り値、名前、引数リスト全体を一般的にシグネチャと呼びます。 シグネチャが衝突しないかぎり、関数の名前は衝突してもコンパイルすることができます。 このような仕組みを関数のオーバーロードと呼びます。
関数のオーバーロードは、同一の機能を提供する関数の呼び出し方法を多様化する目的に利用されます。 まったく異なる機能の関数をオーバーロードすることは、言語仕様上は可能ですが設計上やってはならないことです。
import std.stream;
class Point {
int x , y;
void SetPoint(int x , int y) {
this.x = x;
this.y = y;
}
void SetPoint(Point obj) {
this.x = obj.x;
this.y = obj.y;
}
}
void SetPoint(Point obj , int x , int y) {
obj.x = x;
obj.y = y;
}
void SetPoint(Point obj1 , Point obj2) {
obj1.x = obj2.x;
obj1.y = obj2.y;
}
int main() {
Point point1 = new Point();
Point point2 = new Point();
Point point3 = new Point();
Point point4 = new Point();
point1.SetPoint(100 , 200);
point2.SetPoint(point1);
SetPoint(point3 , 10 , 20);
SetPoint(point4 , point3);
stdout.printf("point1 X=%d,Y=%d\n" , point1.x , point2.y);
stdout.printf("point2 X=%d,Y=%d\n" , point2.x , point2.y);
stdout.printf("point3 X=%d,Y=%d\n" , point3.x , point3.y);
stdout.printf("point4 X=%d,Y=%d\n" , point4.x , point4.y);
return 0;
}
このプログラムは Point クラスのメンバ関数として、フィールドの値を設定する SetPoint() 関数を 2 つ宣言しています。 また、グローバルな関数として SetPoint() 関数を同様に 2 つ宣言しています。 これらの関数は同一の名前を保持していますが、引数が異なるため衝突することはありません。 このとき、Point クラスの SetPoint() 関数、及びグローバルな SetPoint() 関数はオーバーロードされていると表現することができます。 ただし、Point クラスの SetPoint() 関数とグローバルな SetPoint() 関数の間には関係がありません。
関数と同様に、コンストラクタもオーバーロードすることができます。 コンストラクタをオーバーロードすることでオブジェクトの初期化方法を多様化することができます。
import std.stream;
class Point {
int x , y;
this(int x , int y) {
this.x = x;
this.y = y;
}
this(Point obj) {
this.x = obj.x;
this.y = obj.y;
}
}
int main() {
Point point1 = new Point(10 , 100);
Point point2 = new Point(point1);
stdout.printf("point1 X=%d,Y=%d\n" , point1.x , point2.y);
stdout.printf("point2 X=%d,Y=%d\n" , point2.x , point2.y);
return 0;
}
このプログラムの Point クラスでは、数値を受け取り座標を初期化するコンストラクタと、他の Point オブジェクトの座標で初期化するコンストラクタが宣言されています。