La prima cosa da capire qui è che questa parte dei requisiti: super.methodA()
significa che si applica al codice delle classi che estendono A
, in un modo definito in JLS 15.12.4.4-2. Invocazione del metodo usando super
An overridden instance method of a superclass may be accessed by using the keyword super
to access the members of the immediate superclass, bypassing any overriding declaration in the class that contains the method invocation...
Diciamo che vogliamo un modo per creare sottoclassi specifiche di A tali che ogni volta che viene invocato super.methodA()
in questi, è garantito che invece del codice che era in classe A
(fuori dal nostro controllo) sarà esegui un altro codice, definito in alcune sottoclassi di A
(sotto il nostro controllo).
Vediamo quali "strumenti" sono a nostra disposizione per ottenere quanto sopra.
-
È necessario creare sottoclassi alcune, specifiche di A
per richiamare alla mente il modo tradizionale di specializzarsi - sottoclassi, cioè considereremo la sottoclasse di A
(chiamiamola B
) che ridefinisce (sostituisce) methodA
nel modo in cui vogliamo.
-
È necessario forzare una sottoclasse a fornire un codice che possa essere eseguito dove lo vogliamo nella superclasse può essere soddisfatto definendo un metodo astratto, chiamiamolo forcedImplementationInSubclass()
Ora abbiamo tutto ciò di cui abbiamo bisogno.
- Definiremo una classe
B
che estende A
, in modo che tutte le sottoclassi di B
siano anche sottoclassi di A
.
- In
B
, sostituiremo methodA
, quindi la sua implementazione in classe A
non sarà più disponibile per sottoclassi di B
.
- Nel metodo sovrascritto in
B
invocheremo il metodo astratto forcedImplementationInSubclass()
che garantirà che le sottoclassi di B
dovranno definire il codice che alla fine verrà eseguito in methodA
.
Di conseguenza, qualsiasi sottoclasse di B
non sarà in grado di richiamare l'implementazione di methodA
fornita nella classe A
e invece, sarà garantito l'esecuzione del codice definito in alcune sottoclassi di B
.
Estendere B
è il modo per creare sottoclassi specifiche di A
che si comportano come vogliamo. Il codice potrebbe apparire come segue:
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
}
}