2011-09-28 12 views
30

Desidero modificare il modo in cui un metodo di una classe viene eseguito senza sovrascrivere il metodo e solo sovrascrivendo (o estendendo idealmente) la classe interna. Supponiamo che non possa cambiare il fatto che ho bisogno di fare questo (sto modificando un codice di codice open source esistente e ci sarebbe l'attrito nell'estrarre classi o quant'altro).Come sovrascrivere/estendere una classe interna da una sottoclasse?

public class A { 
    static class Thing { 
    public int value() { return 10+value2(); } 
    public int value2() { return 10; } 
    } 

    public String toString() { 
    Thing t = new Thing(); 
    return Integer.toString(t.value()); 
    } 
} 

public class B extends A { 
    static class Thing { 
    public int value2() { return 20; } 
    } 
} 

Il mio obiettivo è, cambiando unica cosa, ottenendo toString di B() per tornare "30", dove attualmente si tornerà "20". L'ideale sarebbe cambiare solo il metodo value2 (lasciando così invariati tutti gli altri metodi), ma non so se sia possibile.

Grazie

risposta

35

Penso che avete bisogno di un metodo di fabbrica per questo. Si consideri il seguente esempio (derivato dal frammento di):

static class A { 
    static class Thing { 
     public int value() { 
      return 10 + value2(); 
     } 
     public int value2() { 
      return 10; 
     } 
    } 
    protected Thing createThing() { 
     return new Thing(); 
    } 
    public String toString() { 
     return Integer.toString(createThing().value()); 
    } 
} 

static class B extends A { 
    static class Thing extends A.Thing { 
     public int value2() { 
      return 20; 
     } 
    } 
    @Override 
    protected Thing createThing() { 
     return new Thing(); // creates B.Thing 
    } 
} 

public static void main(String[] args) { 
    System.out.println(new B()); 
} 

uscita:

30 
+1

Ha ogni grammo di eleganza che speravo. Grazie! –

+3

Dal momento che non l'ho visto all'inizio, voglio sottolineare che questo ha richiesto l'override di createThing nella classe esterna. Credo che non ci sia modo di ignorare i metodi nella classe interna di A "Thing" da una sottoclasse di A. (Mi piacerebbe sentire altrimenti) Invece stai sostituendo A.Thing con un nuovo B.Thing che ombreggia nel namespace di B ma non è visibile ai metodi in A. Per usare questo, è necessario aggiornare ogni riferimento dalla classe esterna. –

2

Non è possibile cambiando solo valore2. Il problema è che le "nuove" chiamate non vengono inviate dinamicamente - il "nuovo" in toString creerà sempre A :: Thing. È possibile risolvere questo problema creando una factory: qualcosa di simile:

public class A { 
    static class Thing { 
    public int value() { return 10+value2(); } 
    public int value2() { return 10; } 
    } 

    private Thing makeThing() { return new Thing(); } 


    public String toString() { 
    Thing t = new Thing(); 
    return Integer.toString(t.value()); 
    } 
} 

public class B extends A { 
    static class Thing extends A.Thing { 
    public int value2() { return 20; } 
    } 

    private Thing makeThing() { return new Thing(); } 

} 
+0

Sembra che tu stia utilizzando la sintassi oggetto C++, Java non è. – Thor84no

3

Si dovrebbe essere in grado di estendere semplicemente la classe interna con Thing extends A.Thing. Finché è visibile nel tuo ambito non dovrebbe essere un problema.

Problemi correlati