views:

114

answers:

6

I'm working on code that's a bit of a mess right now and am doing a lot of refactoring.

Is there a way to move a field from one class to another and update the references automatically? 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 attributes. A reference to the helper class exists as a field in the class I'm refactoring from. In order not to break the code during the refactoring, I think it would be nice if Eclipse offered to to generate getters and setters and update the references so that they use the getters/setters in the new class.

Thanks!

+1  A: 

For a Java function, you can simply right click on its name, then select Refactor > Move. In the wizard, select the new class that will now manage this method.

I think this can help you in your task, even if you can't choose several elements at once that must be moved...

romaintaz
No, Eclipse's move field refactoring basically just cuts and pastes the field, which is surprising given how powerful the other refactorings in Eclipse are.
glenviewjeff
Also, you can choose as many as you want and Eclipse will move them. It just does nothing about the unresolved references to it.
glenviewjeff
I just tried in Eclipse Helios to move one method from one class to another, and Eclipse automatically updated my JUnit tests. So for me, it's not a simple copy / paste operation here...
romaintaz
My question regards fields, not methods.
glenviewjeff
+1  A: 

Won't right click the field > Refactoring > Move do?

Yes, it does not update references, but imagine what would it have to do - in all places where your field is referenced, it will have to instantiate the new class. That's not practical.

Bozho
No, Eclipse's move field refactoring basically just cuts and pastes the field, which is surprising given how powerful the other refactorings in Eclipse are.
glenviewjeff
Or a little more intelligently, it would notice I already have an reference to the object in my class and offer to use that instead.
glenviewjeff
+1  A: 

The move operation on a field won't work appropriately. You can move a field but eclipse won't move the getters and setters. It's an intresting question if this is possible i don't think it is.

kukudas
This is what I was afraid of. I'll have to submit an enhancement request. I can't see any reason why this shouldn't be easily automated.
glenviewjeff
A: 

If the target class doesn't already exist, you can use Refactor > Extract Class. This will create a new class containing the fields you select, and add a field of this type into your original class.

I'm not sure if you can do it for a class that does exist - but you could always use Extract Class and then cut'n'paste its contents into your new class.

Nick
Right, but then the references to the temporary new class are not updated to access the class that I just pasted them into. This won't be any better than just moving them directly to the desired class.
glenviewjeff
+5  A: 

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).

Mark Peters
I don't think my original question was clear about my end goal of the refactoring. Please see the additional info. It looks like Bill K has a good workflow to accomplish what I want.
glenviewjeff
+2  A: 

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.

Bill K