2010-10-04 9 views
10

EDIT: Envié un Eclipse enhancement request for this refactoring.Refactorización para mover un campo privado de una clase a su clase auxiliar?

¿Hay alguna forma de mover un campo privado de una clase a su clase auxiliar? El siguiente UML de rayas de pollo muestra lo que estoy haciendo manualmente ahora. La clase C1 tiene field privado y una referencia final privada a un objeto Helper antes de la refactorización.

Después de la refactorización, todas las referencias en C1' a field se cambian a helper.getField() y helper.setfield() según corresponda.

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; 
    } 
} 

He utilizado las capacidades de refactorización de Eclipse un poco, pero no puedo encontrar una manera de automatizar este.

Por ejemplo, idealmente arrastraría el campo/atributo/miembro privado de una clase a otra y espero que Eclipse me pregunte cómo quiero manejar las referencias no resueltas. No ofrece sugerencias y rompe todas las referencias.

La operación que he estado repitiendo es separar el conocimiento y el comportamiento que realmente no pertenecen a la clase actual. Estoy moviendo atributos y comportamiento que hace referencia a ciertos campos fuera de la clase original en una nueva clase de "ayuda".

El primer paso en mi refactorización es mover los campos. Una referencia a la clase auxiliar existe como un campo en la clase de la que estoy refactorizando. Para no romper C1 durante la refactorización, creo que sería bueno si Eclipse ofreciera generar getters y setters en Helper' y actualizar las referencias en C1 para usar los getters/setters en la nueva clase.

+1

Para información, ¿qué versión de Eclipse estás usando? – romaintaz

+0

3.5, pero trataría de actualizar a 3.6 si esta característica se ha mejorado. Sin embargo, leí las notas de la versión y parece haber poco cambio en 3.6 con respecto a la refactorización. –

Respuesta

2

El asunto es que su campo debe ser privado (ni siquiera sé por qué existe la posibilidad de crear campos públicos no finales). Entonces, ¿cómo podría acceder a él desde otra clase?

Si no desea romperlo durante un refactorio, le puedo dar un pequeño truco que utilizo que a veces me ayuda.

Cuando crea su clase, conviértala ya sea en una clase interna de la clase existente o en una segunda clase en el mismo archivo.

Si la convierte en una clase interna, puede copiar los métodos primero y pueden hacer referencia al miembro de la otra clase. Una vez que obtenga toda la funcionalidad transferida, puede mover la variable. En este punto, ninguna de las referencias a la variable debe actualizarse ya que accede a ella de la misma manera, independientemente de la clase en la que se encuentre.

Hacer una clase en una segunda clase en el mismo archivo puede ser agradable si se está separando funcionalidad también: le permite acceder a todo a la vez sin pasar el ratón entre las ventanas. Cuando hayas terminado, simplemente arrastra la nueva clase en su propio archivo java, vuelve a calcular las importaciones, vuelve a formatear para que sea público y guárdalo.

Casi siempre uso una de estas metodologías cuando creo una nueva clase que interactúa con clases existentes.

0

Para una función de Java, puede simplemente hacer clic derecho en su nombre, luego seleccionar Refactor > Move. En el asistente, seleccione la nueva clase que ahora administrará este método.

Creo que esto le puede ayudar en su tarea, incluso si no se puede elegir varios elementos a la vez que se debe mover ...

+0

No, la refacturación de campo de movimiento de Eclipse básicamente corta y pega el campo, lo cual es sorprendente dado lo poderosas que son las otras refactorizaciones en Eclipse. –

+0

Además, puede elegir tantas como desee y Eclipse las moverá. Simplemente no hace nada sobre las referencias no resueltas a la misma. –

+0

Acabo de probar en Eclipse Helios para mover un método de una clase a otra, y Eclipse actualizó automáticamente mis pruebas JUnit. Entonces, para mí, no es una simple operación de copiar/pegar aquí ... – romaintaz

1

¿No será right click the field > Refactoring > Move hacer?

Sí, no actualiza las referencias, pero imagine lo que tendría que hacer: en todos los lugares donde se hace referencia a su campo, tendrá que crear una instancia de la nueva clase. Eso no es práctico.

+1

No, la refacturación de campo de movimiento de Eclipse básicamente corta y pega el campo, lo cual es sorprendente dado lo poderosas que son las otras refactorizaciones en Eclipse. –

+0

O un poco más inteligente, notaría que ya tengo una referencia al objeto en mi clase y me ofrecería usarlo en su lugar. –

+0

+1 Esto funciona perfectamente bien para constantes. Actualiza fácilmente las referencias también – Ravisha

1

La operación de movimiento en un campo no funcionará correctamente. Puedes mover un campo pero eclipse no moverá los getters y setters. Es una pregunta interesante si esto es posible, no creo que sea así.

+0

Esto es lo que temía. Tendré que enviar una solicitud de mejora. No veo ninguna razón por la cual esto no deba automatizarse fácilmente. –

0

Si la clase de destino no existe todavía, puede usar Refactor > Extract Class. Esto creará una nueva clase que contendrá los campos que seleccione, y agregará un campo de este tipo a su clase original.

No estoy seguro de si puedes hacerlo para una clase que sí existe, pero siempre puedes usar Extract Class y luego cortar el contenido en tu nueva clase.

+0

Correcto, pero las referencias a la nueva clase temporal no se actualizan para acceder a la clase en la que las pegué. Esto no será mejor que moverlos directamente a la clase deseada. –

8

Bueno, simplemente no tiene sentido que esto funcione en general. Semánticamente, es una operación extraña.Si mueve el campo a una clase nueva, disjunta (digamos de Cadena a Entero), el código que hace referencia a ella no tendrá una instancia de la nueva clase para usar para obtener el campo de instancia.

Así que solo hay casos especiales en los que tiene sentido: cuando el campo es un miembro estático, o lo está moviendo a una clase principal.

Para los miembros estáticos, funciona bien hacer clic con el botón derecho en el campo que desea mover (el nombre de la variable) y hacer clic en Refactorizar -> Mover. Elija el nuevo tipo. Las referencias se actualizarán automáticamente (pruébelo usted mismo y vea)

Para cuando lo mueva a/desde una clase para padres, puede usar Refactor-> Levantar o Empujar hacia abajo, pero esto no cambiará automáticamente referencias para usted (solo un problema con Push Down; con el polimorfismo Pull Up dicta que las referencias siguen siendo correctas).

+0

Por supuesto, esto tiene sentido. La clase de ayuda no es una clase disjunta; es una * clase auxiliar * que está contenida por la primera y tiene la misma línea de tiempo que la clase de referencia 'C1'. La clase auxiliar es un campo 'final', por lo que siempre está presente y es accesible. –

+0

@Jeff Respondí esto hace dos años, y antes de que me proporcionara las aclaraciones en su pregunta que lo cambiaron significativamente. Mi punto sigue en pie; * en general * mover un campo a otra clase no siempre es posible. –

Cuestiones relacionadas