まだまだ理解してないというか把握してないことが一杯あるなぁ〜
Java 6u33
継承元のクラスOverloadTestには、init(OverloadTest)メソッドが実装されている。
サブクラスSubclassAは、init(OverloadTest)メソッドをオーバーライドしたメソッドが実装されている。
サブクラスSubclassBは、init(OverloadTest)メソッドをオーバーロードしたinit(SubclassB)メソッドが実装されている。
とした時に、サブクラスSubclassBのinit(SubclassB)メソッドを呼び出す方法はあるんだろうか?
これって、ダイアモンド継承と同じような問題というか制約なんかな???
にしても、呼び出す方法があるんならいいけど、呼び出す方法がない場合はコンパイルエラーにならない理由があるのかな???
本来の形じゃなければ、ダミーの空のインターフェースDummyInterfaceを作って、サブクラスSubclassBはそれを実装して、init(DummyInterface)メソッドをオーバーロード…
でも結局、DummyInterface → SubclassB の型変換をせんといかんのよな。
引き続き、インターフェースでのオーバーロードも確認してみた。
サンプルコード
public class OverloadTest { public static void main(String[] args) { new OverloadTest().test(); } public void test() { System.out.println("\n■■■ OverloadTestの挙動 ■■■"); new OverloadTest().setup(); System.out.println("\n■■■ SubclassAの挙動 → オーバーライドしているため呼び出される ■■■"); new SubclassA().setup(); System.out.println("\n■■■ SubclassBの挙動 → オーバーロードしているinit(SubclassB)は呼び出れない ■■■"); new SubclassB().setup(); } /* initメソッドの呼び出し元 */ public void setup() { System.out.println("==== OverloadTest型の変数でinitを呼び出します ===="); OverloadTest test = new OverloadTest(); init(test); OverloadTest testA = new SubclassA(); init(testA); OverloadTest testB = new SubclassB(); init(testB); System.out.println("==== SubclassA型の変数でinitを呼び出します ===="); SubclassA classA = new SubclassA(); init(classA); System.out.println("==== SubclassB型の変数でinitを呼び出します ===="); SubclassB classB = new SubclassB(); init(classB); System.out.println("==== SubclassB型の変数でキャストしてinitを呼び出します ===="); init((SubclassB) classB); System.out.println("==== SubclassB型の変数でthisで修飾してinitを呼び出します ===="); this.init(classB); System.out.println("==== SubclassB型の変数でキャストしてthisで修飾してinitを呼び出します ===="); this.init((SubclassB) classB); } /* 継承元のinitメソッド */ public void init(OverloadTest test) { System.out.println("OverloadTest#init(OverloadTest)です。"); } /* OverloadTestを継承したクラスA */ public class SubclassA extends OverloadTest { /* 継承元のinitメソッドをオーバーライド */ public void init(OverloadTest test) { System.out.println("SubclassA#init(OverloadTest)です。"); } } /* OverloadTestを継承したクラスB */ public class SubclassB extends OverloadTest { /* 継承元のinitメソッドを継承したクラスBの型でオーバーロード */ public void init(SubclassB test) { System.out.println("SubclassB#init(SubclassB)です。"); } } }
サンプルコードでの実行結果
■■■ OverloadTestの挙動 ■■■ ==== OverloadTest型の変数でinitを呼び出します ==== OverloadTest#init(OverloadTest)です。 OverloadTest#init(OverloadTest)です。 OverloadTest#init(OverloadTest)です。 ==== SubclassA型の変数でinitを呼び出します ==== OverloadTest#init(OverloadTest)です。 ==== SubclassB型の変数でinitを呼び出します ==== OverloadTest#init(OverloadTest)です。 ==== SubclassB型の変数でキャストしてinitを呼び出します ==== OverloadTest#init(OverloadTest)です。 ==== SubclassB型の変数でthisで修飾してinitを呼び出します ==== OverloadTest#init(OverloadTest)です。 ==== SubclassB型の変数でキャストしてthisで修飾してinitを呼び出します ==== OverloadTest#init(OverloadTest)です。 ■■■ SubclassAの挙動 → オーバーライドしているため呼び出される ■■■ ==== OverloadTest型の変数でinitを呼び出します ==== SubclassA#init(OverloadTest)です。 SubclassA#init(OverloadTest)です。 SubclassA#init(OverloadTest)です。 ==== SubclassA型の変数でinitを呼び出します ==== SubclassA#init(OverloadTest)です。 ==== SubclassB型の変数でinitを呼び出します ==== SubclassA#init(OverloadTest)です。 ==== SubclassB型の変数でキャストしてinitを呼び出します ==== SubclassA#init(OverloadTest)です。 ==== SubclassB型の変数でthisで修飾してinitを呼び出します ==== SubclassA#init(OverloadTest)です。 ==== SubclassB型の変数でキャストしてthisで修飾してinitを呼び出します ==== SubclassA#init(OverloadTest)です。 ■■■ SubclassBの挙動 → オーバーロードしているinit(SubclassB)は呼び出れない ■■■ ==== OverloadTest型の変数でinitを呼び出します ==== OverloadTest#init(OverloadTest)です。 OverloadTest#init(OverloadTest)です。 OverloadTest#init(OverloadTest)です。 ==== SubclassA型の変数でinitを呼び出します ==== OverloadTest#init(OverloadTest)です。 ==== SubclassB型の変数でinitを呼び出します ==== OverloadTest#init(OverloadTest)です。 ==== SubclassB型の変数でキャストしてinitを呼び出します ==== OverloadTest#init(OverloadTest)です。 ==== SubclassB型の変数でthisで修飾してinitを呼び出します ==== OverloadTest#init(OverloadTest)です。 ==== SubclassB型の変数でキャストしてthisで修飾してinitを呼び出します ==== OverloadTest#init(OverloadTest)です。
実際の対応
オーバーロードである必要性はなかったので、オーバーライドしてから型変換するという対応とした。
public class SubclassB extends OverloadTest { /* 継承元のinitメソッドをオーバーライド */ public void init(OverloadTest arg ) { // SubclassBに型変換 SubclassB test = (SubclassB) arg ; /* * SubclassBでの処理 */ } }