Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refactoring to move a private field from one class to its helper class?

EDIT : I submitted an Eclipse enhancement request for this refactoring.

Is there a way to move a private field from one class to its helper class? The below chicken-scratch UML shows what I'm doing manually right now. Class C1 has private field and a private final reference to a Helper object before the refactoring.

After the refactoring, all references in C1' to field are changed to helper.getField() and helper.setfield() as appropriate.

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

I've used Eclipse's refactoring capabilities quite a bit, but I can't figure out a way to automate this.

For instance, ideally I would drag the private field/attribute/member from one class to another and hope that Eclipse asks me how I want to handle the unresolved references. It offers no suggestions and breaks all of the references.

The operation that I've been repeating is to separate knowledge and behavior that doesn't really belong in the current class. I'm moving attributes and behavior that references certain fields out of the original class into a new "helper" class.

The first step in my refactoring is to move the fields. A reference to the helper class exists as a field in the class I'm refactoring from. In order not to break C1 during the refactoring, I think it would be nice if Eclipse offered to to generate getters and setters in Helper' and update the references in C1 to use the getters/setters in the new class.

like image 250
Jeff Axelrod Avatar asked Oct 04 '10 20:10

Jeff Axelrod


People also ask

How do I move a method from one class to another in Intellij?

Open your class in the editor, place a caret at the static method you want to move and press F6 . In the Move Members dialog specify the following options: In the Members to be moved to another class (static only) field, select the checkboxes next to the methods that you want to move to another class.

How do you move a method from one class to another in python?

If you go to each method and right-click on its name, the menu has a "Refactor" option, which leads to a "Move" option. Select that and follow the instructions. The above is especially easy for static methods. For the non-static ones, you may need to do subclassing, or pass references to the appropriate objects around.

How do I move a method from one class to another in Eclipse?

To move this method to the new class, highlight the method's name and select Refactor→ Move, or right-click and select Refactor→ Move, opening the Move Static Member(s) dialog shown in Figure 4-5. In Eclipse, you can move a static method, static field, or instance method using refactoring.


2 Answers

Well, it simply doesn't make sense for this to work in general. Semantically, it's a weird operation. If you move the field to a new, disjoint class (say from String to Integer) the code that referenced it wouldn't have an instance of the new class to use to get the instance field.

So there are only special cases where it makes sense: when the field is a static member, or you're moving it to a parent class.

For static members, it works fine to right-click on the field you want to move (the variable name), and click Refactor->Move. Choose the new type. References will automatically be updated (try it yourself and see)

For when you're moving it to/from a parent class, you can use Refactor->Pull Up or Push Down, but this will not automatically change references for you (only an issue with Push Down; with Pull Up polymorphism dictates that the references are all still fine).

like image 88
Mark Peters Avatar answered Oct 21 '22 14:10

Mark Peters


The thing is, your field must be private (I don't even know why the ability to create public non-final fields exists). So how could you possibly access it from another class?

If you don't wish to break it during a refactor I can give you a little trick I use that kinda helps sometimes.

When you create your class, make it either an inner class of the existing class or a second class in the same file.

If you make it an inner class you can copy the methods over first and they can refer to the member in the other class. Once you get all the functionality ported over you can move the variable. At this point none of the references to the variable should be updated since you access it the same way regardless of which class it was in.

Making a class a second class in the same file can be nice if you are splitting apart functionality as well--it lets you access everything at once without mousing between windows. When you are done just drag the new class into it's own java file, recalculate imports, reformat make it public and save it.

I nearly always use one of these methodologies when creating a new class that interacts with existing classes.

like image 31
Bill K Avatar answered Oct 21 '22 12:10

Bill K