public interface MyInterface {}
public class A implements MyInterface{}
public class B implements MyInterface{}
public class Tester {
public static void main(String[] args){
MyInterface a = new A();
MyInterface b = new B();
test(b); // this is wrong
}
public static void test(A a){
System.out.println("A");
}
public static void test(B b){
System.out.println("B");
}
}
MyInterfaceのようなサブタイプを持つ引数で定義されたメソッドに、参照変数によって参照されるオブジェクトを渡そうとしていますtest(B b)。MyInterface参照変数は のサブタイプである任意のオブジェクトを参照できますが、MyInterface必ずしも のオブジェクトであるとは限りませんB。これが Java で許可されている場合、実行時エラーが発生する可能性があるため、コンパイラはここでエラーを出します。概念をより明確にする例を挙げてください。クラスのコードを変更しB、メソッドを追加しました。
public class B implements MyInterface {
public void onlyBCanInvokeThis() {}
}
test(B b)以下のようにメソッドを変更するだけです:
public static void test(B b){
b.onlyBCanInvokeThis();
System.out.println("B");
}
コンパイラで許可されている場合、このコードは実行時に爆発します。
MyInterface a = new A();
// since a is of type A. invoking onlyBCanInvokeThis()
// inside test() method on a will throw exception.
test(a);
これを防ぐために、コンパイラは、スーパークラス参照を使用したこのようなメソッド呼び出し手法を許可しません。
何を達成しようとしているのかはわかりませんが、実行時のポリモーフィズムを達成したいようです。MyInterfaceこれを実現するには、メソッドを宣言し、それを各サブクラスに実装する必要があります。このようにして、メソッドの呼び出しは、参照型ではなくオブジェクト型に基づいて実行時に解決されます。
public interface MyInterface {
public void test();
}
public class A implements MyInterface{
public void test() {
System.out.println("A");
}
}
public class B implements MyInterface{
public void test() {
System.out.println("B");
}
}
public class Tester {
public static void main(String[] args){
MyInterface a = new A();
MyInterface b = new B();
b.test(); // calls B's implementation of test()
}
}