日本語では多重定義と訳される。
一口に言えば、「同じ名前の関数(や演算子)をいくつもつくって、引数に合わせて動作を変える」というテクニック。
多態性(ポリーモフィズム(Polymorphism))を実現するためには必須のテクニック。
演算子のオーバーロードには対応していない言語も多いので、ここでは関数(メソッド)のオーバーロード、特に使う機会の多いコンストラクタのオーバーロードについて解説。
コンストラクタの引数によって、メソッドの動作を変化させたい場合を考える。
例としてファイルを扱うFileStreamクラスを考えてみる。
このクラスのコンストラクタは
・引数として文字列が指定されたら、その文字列でファイルを開き、扱える状態にする。
・なにも指定されなかったら、メモリ領域だけを確保する。
というもの。これを満たすには、下のように二つのコンストラクタを定義すればよい。
pointer FileStream(String[]) {}
pointer FileStream(void){}
後はコンパイラが必要に応じて適したほうを選択、実行できるようにしてくれる。
これがC言語のようにオーバーロードをサポートしていない言語だと、とりあえずFileStream(char*)などとして定義しておいて、それが空かどうかで処理を分岐させるような小手先のテクニックが必要になる。
それに対してオーバーロードを使えば、役割ごとに違うメソッドが呼ばれるので、コードが見やすくなるし、よりオブジェクトらしい動きをクラスにさせることができる。
ただし、多用のしすぎは逆にプログラムを分かりづらくするので注意が必要。
親クラス(スーパークラス)で定義されたメソッドを、子クラス(サブクラス)で再定義するテクニック。再定義などと呼ぶ。
これもポリモーフィズムを実現するためのテクニックとしてよく用いられる。
名前が似ているけれど、オーバーロードと混同しないように注意。
例えば、VIPというクラスを継承して、VIP+というクラスを作るとする。
(書き方はJava風だが、中身は適当なので注意。)
class VIP {
VIP(){...} // コンストラクタ
// ↓このメソッドをオーバーライドしてみる
スレッド作成{
if(2ch.アクセス規制(me)){
Thread.new("プログラミングスレ") ;
}
}
}
class VIP+ extends VIP {
VIP+(){...} // コンストラクタ
// オーバーライドされたメソッド
@Override スレッド作成{
if(2ch.アクセス規制(me)){
Thread.new("VIP+で立てられたプログラミングスレ") ;
}
}
}
この状態でVIP+クラスのインスタンスを作成し、スレッド作成メソッドを呼び出すと、VIP+クラスでオーバーライドされた方のメソッドが呼び出される。
これは、VIPクラス型の変数にたいしてVIP+のインスタンスを入れても同様。つまり
VIP hoge = new VIP+() ;
hoge.スレッド作成 // ←VIP+クラスのスレッド作成メソッドが呼ばれる
という結果になる。親クラスでしていたのと別の動作をさせたい時にオーバーライドがよく使われる。
特に、あるスーパークラスから複数のクラスを派生させるような場合に使われる。
具体例を挙げると、Delphiではほぼ全てのクラスのデストラクタは、少なくともTObjectメソッドのデストラクタをオーバーライドしている。
ちなみに、継承先(サブクラス)でオーバーライドされるための関数(継承元(スーパークラス)の中ではなにもしない)を、純粋仮想関数などと呼ぶ。