私は以下を持っています:
public Class A { public void methodA(){ .... } public void methodB(){ .... } }
Class Aを制御できません。methodA()をオーバーライドする必要があるという制限付きでClass Aのサブクラスを作成したいと思います(super.methodA()呼び出しでClass Aの実装を実行する必要があります)。出来ますか?そうですか?
ここで最初に理解することは、要件のこの部分:super.methodA()
は、これがA
を拡張するクラスのコードに適用されることを意味します JLS 15.12.4.4-2。super
を使用したメソッド呼び出し
スーパークラスのオーバーライドされたインスタンスメソッドにアクセスするには、キーワード
super
を使用して直接のスーパークラスのメンバーにアクセスし、メソッド呼び出しを含むクラスのオーバーライド宣言をバイパスします...
たとえば、Aの特定のサブクラスを作成して、これらでsuper.methodA()
が呼び出されるたびに、クラスA
にあるコード(コントロール外)の代わりに、いくつかが実行されることが保証されるとしましょうA
のサブクラスで定義された他のコード(私たちの制御下)。
上記を達成するために私たちが自由に使える「ツール」を見てみましょう。
A
のsome、specificサブクラスを作成する必要があるため、従来の特殊化の方法が思い浮かびます-サブクラス化、つまり、A
のサブクラス(B
と呼びましょう)を検討して、methodA
を再定義(オーバーライド)します私たちが望む方法。
サブクラスにスーパークラスで実行したい場所で実行するコードを提供する必要がある場合は、抽象メソッドを定義することで満たすことができます。それをforcedImplementationInSubclass()
と呼びましょう。
これで、必要なものがすべて揃いました。
B
を拡張するクラスA
を定義し、B
のすべてのサブクラスがA
のサブクラスになるようにします。B
では、methodA
をオーバーライドするため、クラスA
での実装をB
のサブクラスで使用できなくなります。B
のオーバーライドされたメソッドで、抽象メソッドforcedImplementationInSubclass()
を呼び出します。これにより、B
のサブクラスが、最終的にmethodA
で実行されるコードを定義する必要があります。その結果、B
のサブクラスは、methodA
クラスで提供されるA
実装を呼び出すことができなくなり、代わりに、B
のサブクラスで定義されたコードを実行することが保証されます。
B
の拡張は、希望どおりに動作するA
の特定のサブクラスを作成する方法です。コードは次のようになります。
public abstract class B extends A {
// override, so that subclasses of B won't be able to get to super.methodA
@Override public void methodA() {
// invoke abstract method here (subclass would have to implement it)
forcedImplementationInSubclass();
}
// define abstract method so that subclass would have to implement it
protected abstract void forcedImplementationInSubclass();
}
// extending B is the way to get what we need
public class C extends B {
// enforced implementation of the abstract method
@Override protected void forcedImplementationInSubclass() {
// that will be invoked when B.methodA() is called, and since B is-a A...
System.out.print("Hello from implemented methodA");
}
public void testSuperMethodA() {
// that will invoke B.methodA() which won't go to class A
super.methodA();
}
public static void main(String[] args) {
A a = new C();
a.methodA(); // goes to B.methodA(), which in turn invokes C.forcedImplementationInSubclass()
C c = new C();
c.testSuperMethodA(); // won't go to class A
}
}
メソッドに実装が与えられると、再び抽象化する方法はありません。したがって、いいえ、A
を変更しない限り、クラスを書く方法はありませんB extends A
そのため、B
のすべてのサブクラスは、少なくとも型システムを介さずに、別の実装を提供する必要があります。
最善の方法は、実行時に例外をスローするメソッドをB
に記述することです。これにより、すべてのサブクラスがメソッドをオーバーライドして強制的に使用できるようになりますが、それを行わなくてもコンパイルされます。