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.
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 get开发者_运维技巧ters/setters in the new class.
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).
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.
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.
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.
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...
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.
精彩评论