2010-10-04 18 views
10

EDIT: Ho inviato un Eclipse enhancement request for this refactoring.Rifattorizzazione per spostare un campo privato da una classe alla sua classe helper?

C'è un modo per spostare un campo privato da una classe alla sua classe helper? L'UML sotto zero di pollo mostra cosa sto facendo manualmente in questo momento. La classe C1 ha privato field e un riferimento finale privato a un oggetto Helper prima del refactoring.

Dopo il refactoring, tutti i riferimenti in C1' a field vengono modificati in helper.getField() e helper.setfield() in base alle esigenze.

UML Diagram

class Field {} 

class C1 { 
    final private Field field; 
    final private Helper helper; 

    public Field getField() { 
     return field; 
    } 

    public C1() { 
     helper = new Helper(); 
     field = new Field(); 
    } 
} 

class Helper {} 

class C1Prime { 
    final private HelperPrime helper; 

    public Field getField() { 
     return helper.getField(); 
    } 

    public C1Prime() { 
     helper = new HelperPrime(); 
    } 
} 

class HelperPrime { 
    final private Field field; 
    public HelperPrime() { 
     field = new Field(); 
    } 
    public Field getField() { 
     return field; 
    } 
} 

ho usato le funzionalità di refactoring di Eclipse un bel po ', ma non riesco a trovare un modo per automatizzare questo.

Ad esempio, preferirei trascinare il campo/attributo/membro privato da una classe all'altra e spero che Eclipse mi chieda come voglio gestire i riferimenti non risolti. Non offre suggerimenti e interrompe tutti i riferimenti.

L'operazione che ho ripetuto è separare conoscenze e comportamenti che non appartengono realmente alla classe corrente. Sto spostando attributi e comportamenti che fanno riferimento a determinati campi della classe originale in una nuova classe "helper".

Il primo passo nel mio refactoring è spostare i campi. Un riferimento alla classe helper esiste come un campo nella classe da cui mi sto rifacendo. Per non rompere C1 durante il refactoring, penso che sarebbe bello se Eclipse offrisse di generare getter e setter in Helper' e aggiornare i riferimenti in C1 per utilizzare i getter/setter nella nuova classe.

+1

Per informazioni, quale versione di Eclipse stai usando? – romaintaz

+0

3.5, ma proverei l'aggiornamento a 3.6 se questa funzione fosse migliorata. Tuttavia, ho letto le note di rilascio e sembra poco cambiato in 3.6 rispetto al refactoring. –

risposta

2

Il fatto è che il campo deve essere privato (non so nemmeno perché esista la possibilità di creare campi non definitivi pubblici). Quindi, come hai potuto accedervi da un'altra classe?

Se non si desidera romperlo durante un refactor, posso darti un piccolo trucco che uso a volte aiuta.

Quando si crea la classe, renderla una classe interna della classe esistente o una seconda classe nello stesso file.

Se si crea una classe interna, è possibile copiare prima i metodi e possono fare riferimento al membro nell'altra classe. Una volta che tutte le funzionalità sono state portate su di voi, è possibile spostare la variabile. A questo punto nessuno dei riferimenti alla variabile deve essere aggiornato poiché lo si accede allo stesso modo indipendentemente dalla classe in cui si trovava.

Rendere una classe una seconda classe nello stesso file può essere buona se ci si divide funzionalità pure: ti consente di accedere a tutto in una volta senza mouse tra le finestre. Quando hai finito trascina la nuova classe nel proprio file java, ricalcola le importazioni, riformatta rendila pubblica e salvala.

Quasi sempre utilizzo una di queste metodologie durante la creazione di una nuova classe che interagisce con le classi esistenti.

0

Per una funzione Java, è sufficiente fare clic con il tasto destro sul suo nome, quindi selezionare Refactor > Move. Nella procedura guidata, seleziona la nuova classe che ora gestirà questo metodo.

Penso che questo può aiutare nel vostro compito, anche se non è possibile scegliere diversi elementi in una sola volta che deve essere spostata ...

+0

No, il refactoring del campo di movimento di Eclipse fondamentalmente taglia e incolla il campo, il che è sorprendente dato quanto sono potenti gli altri refactoring in Eclipse. –

+0

Inoltre, puoi scegliere quante ne vuoi e Eclipse le sposterà. Semplicemente non fa nulla per i riferimenti irrisolti ad esso. –

+0

Ho appena provato in Eclipse Helios di spostare un metodo da una classe all'altra ed Eclipse ha aggiornato automaticamente i miei test JUnit. Quindi per me, non è una semplice operazione di copia/incolla qui ... – romaintaz

1

Will not right click the field > Refactoring > Move fare?

Sì, non aggiorna i riferimenti, ma immagina cosa avrebbe dovuto fare - in tutti i punti in cui è indicato il campo, dovrà istanziare la nuova classe. Non è pratico.

+1

No, il refactoring del campo di movimento di Eclipse fondamentalmente taglia e incolla il campo, il che è sorprendente considerando la potenza degli altri refactoring in Eclipse. –

+0

O un po 'più intelligentemente, noterebbe che ho già un riferimento all'oggetto nella mia classe e propongo di usarlo. –

+0

+1 Funziona perfettamente per le costanti. Aggiorna facilmente anche i riferimenti – Ravisha

1

L'operazione di spostamento su un campo non funzionerà in modo appropriato. Puoi muovere un campo ma eclissi non sposterà getter e setter. È una domanda interessante se questo è possibile non credo che lo sia.

+0

Questo è ciò di cui avevo paura. Dovrò presentare una richiesta di miglioramento. Non vedo alcun motivo per cui questo non dovrebbe essere facilmente automatizzato. –

0

Se la classe di destinazione non esiste già, è possibile utilizzare Refactor > Extract Class. Questo creerà una nuova classe contenente i campi selezionati e aggiungerà un campo di questo tipo nella tua classe originale.

Non sono sicuro che lo si possa fare per una classe che esiste, ma è sempre possibile utilizzare Extract Class e quindi tagliare i contenuti nella nuova classe.

+0

Giusto, ma i riferimenti alla nuova classe temporanea non vengono aggiornati per accedere alla classe in cui li ho appena incollati. Questo non sarà migliore del semplice spostamento diretto nella classe desiderata. –

8

Beh, semplicemente non ha senso che funzioni in generale. Semanticamente, è una strana operazione.Se si sposta il campo su una nuova classe disgiunta (ad esempio da String a Integer), il codice che lo ha fatto riferimento non avrebbe avuto un'istanza della nuova classe da utilizzare per ottenere il campo dell'istanza.

Quindi ci sono solo casi speciali in cui ha senso: quando il campo è un membro statico, o lo si sta spostando in una classe genitore.

Per i membri statici, funziona correttamente per fare clic con il pulsante destro del mouse sul campo che si desidera spostare (il nome della variabile) e fare clic su Riformatore-> Sposta. Scegli il nuovo tipo. I riferimenti verranno automaticamente aggiornati (provalo tu stesso e vedi)

Per quando lo si sposta da/verso una classe genitore, è possibile utilizzare Refactor-> Pull Up o Push Down, ma questo non cambierà automaticamente riferimenti per te (solo un problema con Push Down, con il polimorfismo Pull Up impone che i riferimenti sono ancora tutti bene).

+0

Ovviamente questo ha senso. La classe helper non è una classe disgiunta; è una * classe helper * che è contenuta nella prima e ha la stessa timeline della classe di riferimento 'C1'. La classe helper è un campo 'finale', quindi è sempre presente e accessibile. –

+0

@Jeff Ho risposto a questo due anni fa, e prima di fornire i chiarimenti nella tua domanda che l'ha cambiato in modo significativo. Il mio punto è ancora valido; * in generale * spostare un campo in un'altra classe non è sempre possibile. –

Problemi correlati