2011-01-07 2 views
5

Ho una raccolta di classi concrete che definiscono un'API e vorrei estrarre l'interfaccia di queste classi (ovvero: essenzialmente la gerarchia di tipi e metodi pubblici) dal implementazione effettiva dell'API.Modo automatizzato per estrarre interfacce da una classe Java

Così, per esempio, se una delle classi pubbliche API è

public class Foo extends Bar { 
    /* some fields which I don't care about */ 

    public void method() { 
    /* implementation here */ 
    } 

    public void otherMethod() { 
    /* implementation goes here */ 
    } 

    /* some non public methods which I don't care about */ 

} 

desidero penetrare un'interfaccia e un'implementazione

cioè

public interface FooInterface extends BarInterface { 
    public void method(); 
    public void otherMethod() 
} 

public class Foo implements FooInterface { 
    /* etc etc */ 
} 

e

C'è uno strumento che posso usare per fare questa separazione in modo automatico, o sono andando a dover rollare il mio programma per fare il lavoro? Deve essere uno strumento che richiede interazione minima.

risposta

5

Ho trovato la soluzione!

Eclipse, ha il supporto per il refactoring degli script, gli script sono in xml ma non molto amichevoli ma ho comunque generato gli script che fanno eseguire a Eclipse tutti i refactoring.

Per i dettagli di refactoring sceneggiatura eclissi, look here e utilizzare Eclipse per generare un paio di esempi per voi in modo da sapere ciò che lo script dovrebbe essere simile

+0

Questo è esattamente quello che stavo cercando (ho lo scenario esatto che hai menzionato)! Qualche possibilità di condividere lo script di refactoring che hai usato? Scoprirò Eclipse per scoprirlo, ma potrei usare qualsiasi aiuto. Grazie in anticipo! – scorpiodawg

+0

Wow, l'XML generato nello "script" non è bello (come in Eclipse Indigo). Riferirò se ottengo qualcosa di utile da questo. – scorpiodawg

3

Molti IDE, come IntelliJ, hanno un comando "Extract Interface" che svolge una refactoring per voi: http://www.jetbrains.com/idea/features/refactoring.html#Extract_Interface

+1

può funzionare su più file contemporaneamente? Diciamo selezionare tutte le classi in un pacchetto ed eseguire l'estrazione di interfaccia? – hhafez

+1

Se si sta facendo questo a tutti i file per motivi di "purezza", suggerisco di ripensare a quali benefici si stanno effettivamente ottenendo. Personalmente, vorrei estrarre l'interfaccia dove e quando aveva senso e lasciare tutto il resto così com'è. Ma poi, non conosco il tuo ragionamento. – Synesso

+0

Non è per "purezza" e non sarà per ogni classe, ma sarebbe noioso fare uno per uno. – hhafez

1

Sono abbastanza sicuro che si dovrà rotolare il proprio strumento per fare questo lavoro; non è qualcosa che molti sviluppatori userebbero, e chi lo ha usato non lo userebbe spesso. L'interfaccia di estrazione, per essere eseguita correttamente, richiede davvero l'intelligenza (il vero tipo) che la guida. Uno strumento che estraeva ciecamente tutti gli elementi protetti pubblici & e ha costruito ciecamente una gerarchia di interfacce per rispecchiare una gerarchia di implementazione, è tutt'altro che intelligente e il prodotto finale non sarebbe bello. Sviluppare l'intelligenza (artificiale) per prendere buone decisioni su cosa includere e cosa portare avanti - sarebbe uno strumento utile, ma confesso inimmaginabilmente difficile per me. Ciò che gli IDE attuali offrono - assistenza guidata - è probabilmente il miglior compromesso. Tirati su; è sempre meno noioso di fare ogni passo a mano!

+0

Sono d'accordo in generale, l'output non sarebbe bello, ma è un punto di partenza ed è proprio quello che mi serve in questa particolare situazione (l'API che voglio rifrattore è in realtà autogenerata da un altro strumento quindi la struttura è in realtà ben definito e quindi lo strumento di refactoring può essere abbastanza intelligente in questo caso) – hhafez

3

javap, uno strumento nel JDK, ti porterà la maggior parte di ciò che si volere. Tuttavia, sii pronto a non gestire correttamente alcune cose - scusa, dimentico cosa, forse annotazioni, classi interne, qualcosa del genere.

Se l'incorporamento javap nel proprietario di Java app avrebbe aiutato, si può fare qualcosa di simile:

import sun.tools.javap.Main; 
... 
    void javap(String className) throws IOException 
    { 
     bos = new ByteArrayOutputStream(); 
     ourOut = new PrintStream(bos); 

     PrintStream oldOut = System.out; 
     System.setOut(ourOut); 

     String[] params = new String[] {"-public", className}; 
     Main.main(params); 

     System.setOut(oldOut); 

     String str = bos.toString(); 
    } 

Ciò richiede l'tools.jar Sun JDK nel classpath.