Move Refactoring & Non-Static Fields

I'm pretty confident that I have seen a refactoring in IDEA that allows me to move non-static fields from an outer class to a contained class, but I can't find it any longer.

class A {}
class B { private A a; private int x; public int getX() {...} }

The refactoring should move 'x' and its' getter to A. However, if I put the cursor on 'x' and choose the Move Refactoring (F6) I get a warning dialog telling me that moves only work for static fields. Hmm, why?

Is there such a refactoring?

11 comments

Hello tom,

I'm pretty confident that I have seen a refactoring in IDEA that
allows me to move non-static fields from an outer class to a contained
class, but I can't find it any longer.

class A {}
class B { private A a; private int x; public int getX() {...} }
The refactoring should move 'x' and its' getter to A. However, if I
put the cursor on 'x' and choose the Move Refactoring (F6) I get a
warning dialog telling me that moves only work for static fields. Hmm,
why?

Is there such a refactoring?


No, there isn't.

--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"


0

Hi Dmitry, your response leaves the 'hm, why?' part open ;) For me, this would this be a reasonable feature request. What do you think?

0

i think i'd like to use it if it was there. i like to move stuff around in general. it's my style of coding.

0

Hi Tom,
Move should preserve program semantics like most of Idea's refactorings do. Having said this, I wonder how you are going to deal with nonstatic field references?

Eugene.

0

Eugene,

good point. In the example above, I guess I'd need IDEA to introduce a getter such as this one in B:

public getX() { return a.getX(); }

This should pretty much preserve semantics.

0

...and BTW, simply want to avoid the copy/paste orgy necessary to achieve this. I would intentionally break semantics even if IDEA gives me a warning.

0

Eugene,

good point. In the example above, I guess I'd need
IDEA to introduce a getter such as this one in B:

public getX() { return a.getX(); }
This should pretty much preserve semantics.


Tom,

To do this, another question should be answered: How to create a in B?

T.

0

Ok, the example above wasn't complete. Add a constructor to B and you should be there.

class B { public B() { a = new A(); } /* see above */ }

Or did I miss something?

0

tom quas wrote:

Ok, the example above wasn't complete. Add a constructor to B and you should be there.

class B { public B() { a = new A(); } /* see above */ }

Or did I miss something?


If what you mean is that IDEA should create a new class, containing
and encapsulating a number of fields that were previously part of the
existing class B, then what you're talking about makes sense. For
example, class B could contain fields x and y, and they could be moved
to a new "Position" class which is instantiated in the B constructor
when a new B is created, and new getters could be created that delegate
to the new Position object.

Your earlier descriptions sound more like you want to move a field from
an existing class B to an existing class A. Then we might assume that A
already has some reason for existing, other than just holding values
that were previously part of B, which makes everything far more
complicated and would only make sense under far more restrictive
circumstances.

For example, you can't be sure that you can just create a new A without
giving a number of constructor arguments. And just creating a new A
might not be what you want in all cases; maybe you want to move a field
from B to an existing instance of A which is already associated with an
instance of B, in some way that may not be easy for IDEA to determine.

0

In your situation, A only have A(), it's OK. But

+ Maybe class A can have several constructors, which constructor will you use? It leads to you need to provide the input to construct A(). Where are they from?
+ Maybe it can be created from factory methods. Same above problem if factory methods need input.
+ or maybe it can be injected from outside
+ ...

IMHO, it's really hard to implement this feature.

0

maybe idea should simply add a constructor parameter providing the A that B will use, just like refactorj's "extract class" does?

0

Please sign in to leave a comment.