オーバーロード
同じ名前のメソッド
クラス内に同じ名前のメソッドがあっても、パラメータの数、またはパラメータの型が異なっていれば、呼び出し式で渡された引数から、どのメソッドを呼び出すか識別できます。メソッドの名前、パラメータの数、型など、メソッド呼び出しの識別に用いられる一連の要素を総称してシグネチャ(signature)と呼びます。
メソッドは名前だけではなくシグネチャで識別されるため、クラス内で同じ名前のメソッドを複数宣言することができます。シグネチャが異なっていれば、メソッド名が同じでも識別できます。逆に、シグネチャが同じメソッドを同じスコープ内で複数宣言することはできません。
同じ名前でパラメータの数や型が異なるメソッドが複数宣言されている状態をオーバーロード(overload)と呼びます。
class A { public void M() { } public void M(int i) { } }
例えば、上記の A クラスの M() メソッドはオーバーロードされています。これら M() メソッドは名前が同じですが、パラメータを受け取らない M() メソッドと、int 型のパラメータを受け取る M(int) メソッドなので、シグネチャが異なります。
オーバーロードされたメソッドの呼び出しでは、渡される引数から識別できます。上記の M() メソッドは、以下のように呼び出しを区別できます。
A obj = new A(); obj.M(); //M() obj.M(10); //M(int)
このように、同じ名前のメソッドをパラメータで区別して呼び出せます。
オーバーロードされたメソッドの処理はパラメータの違いのみで、それ以外は共通した機能を提供するべきです。同じ名前のオーバーロードされたメソッドが無関係な処理を実行するのは、不要な混乱を生むだけです。一般的な設計では、オプション的なパラメータを省略できるメソッドと、詳細な動作をパラメータで指定できるメソッドの双方を提供するためにオーバーロードが用いられます。
class MagicalGirl { public void Attack() { System.Console.WriteLine("Attack"); } public void Attack(string magicWord) { System.Console.WriteLine("Attack: " + magicWord); } } class Test { public static void Main(string[] args) { MagicalGirl mami = new MagicalGirl(); mami.Attack(); mami.Attack("ティロ・フィナーレ"); } }
コード1の MagicalGirl クラスはオーバーロードされた 2 つの Attack() メソッドを宣言しています。実行結果のように、メソッドの呼び出し式で渡した引数によって、実行するべきメソッドが適切に識別されています。
コンストラクタのオーバーロード
メソッドと同様に、コンストラクタもオーバーロードできます。コンストラクタの呼び出しも new 演算子によるオブジェクト作成式のときに渡す引数によって識別されます。多くの場合、オブジェクトを初期化するための初期値を受け取るコンストラクタと、既定の初期値で初期化するコンストラクタなどでオーバーロードします。
class MagicalGirl { public MagicalGirl() { System.Console.WriteLine("MagicalGirl"); } public MagicalGirl(string spell) { System.Console.WriteLine("MagicalGirl: " + spell); } } class Test { public static void Main(string[] args) { new MagicalGirl(); new MagicalGirl("Stand by Ready"); } }
コード2 の MagicalGirl クラスのコンストラクタはオーバーロードされています。どのコンストラクタで初期化されるかはオブジェクト作成式でコンストラクタに渡された引数から識別されます。