オーバーロードとオーバーライドは似て非なる挙動をします。
/*
ClassA <|- ClassB
の継承関係で、オーバーライドとオーバーロードを試す
*/
class ClassA{
void overridedMethod(){
System.out.println("by ClassA");
}
}
class ClassB extends ClassA{
void overridedMethod(){
System.out.println("by ClassB");
}
}
class TestMain{
static void overloadedMethod(ClassA a){
System.out.println("for ClassA");
}
static void overloadedMethod(ClassB b){
System.out.println("for ClassB");
}
/* 以下、テスト実行メソッド */
static public void main(String[] str){
ClassA a = new ClassB();
// オーバーライドなメソッドを呼び出してみる
a.overridedMethod();
// オーバーロードなメソッドを呼び出してみる
overloadedMethod(a);
}
}
/*
(実行結果)
by ClassB
for ClassA
*/オーバーロードはコンパイル時にメソッドが選択、つまり、変数の宣言されている型で判断されているようです。このオーバーロードの動きは直感的ではないので、オーバーロードで継承関係にあるクラスを利用するのは避けるべきです(と、Effective javaに書かれていました(笑) )。
なんでこんなこと調べたかと言うと、void traceLog(Throwable e)とvoid traceLog(Exception e)が定義されている例を実際に見かけたもんで・・・。この場合はThrowableの文だけ定義しておくべきでしょう。
ついつい、自分でもこういう嫌な実装をやってしまわないように気をつけたいものです。