0

I have refactored my method using "Introduce a parameter" as it was accepting a lot of variables. but now all the callers have inline cosntructor as

this.somemethod(new MyParam("a", "b","c","d"); 

i would like to refactor it by replacing constructor with setters like

MyParam myParam= new MyParam();
myParam.setA("a");........
.
.
this.somemethod(myParam);

Is there someway to do this ??

there was a similar bug reported on eclipse https://bugs.eclipse.org/bugs/show_bug.cgi?id=105324

Nitin Chhajer
  • 2,299
  • 1
  • 24
  • 35
Edge
  • 722
  • 2
  • 7
  • 21
  • 1
    Are you really sure you want to do that? Maybe you want to split MyParam into several classes instead... – claesv Apr 25 '12 at 08:30
  • 1
    basically i dont like long line of code as it becomes really diffcult to read and very diffcult to understand what parameters are getting passed – Edge Apr 25 '12 at 08:32

3 Answers3

3

Is there someway to do this ??

Yes, have setter-like functions that return this so you can chain them:

public class MyParam {
    private String foo;
    private int bar;
    // ...and so on...

    public MyParam() {
        // Set reasonable defaults here
    }

    public MyParam letFoo(String foo) {
        this.foo = foo;
        return this;
    }

    public MyParam letBar(int bar) {
        this.bar = bar;
        return this;
    }

    // ...and so on...
}

Usage:

someFunction(new MyParam()
             .letFoo("foo")
             .letBar(42)
             .letXyz(...)
             // ...and so on...
);

This is particularly useful when A) There are reasonable defaults for several of the "parameters" and so callers won't necessarily have to use all the setters, and B) There are lots of parameters so it's easy to get lost in the order of things.

I've used letXyz rather than setXyz because as Sean points out in the comments, setXyz uses the JavaBean naming convention, but JavaBean setters shouldn't have a return value. (For more, see this other question here on SO and its answers.)

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • +1 but I disagree about the naming. setXyz suggests Java bean methods, which they aren't (Java Beans setters may not have a return value). I'd call the methods "withXyz" or something like that, after all you are building something. – Sean Patrick Floyd Apr 25 '12 at 08:35
  • @SeanPatrickFloyd: Good point. I don't like either `setFoo` or `withFoo`, but the name is less important than the concept. – T.J. Crowder Apr 25 '12 at 08:37
  • I wanted to it with refactoring as i'll endup changing a lot of files otherwise. – Edge Apr 25 '12 at 08:37
  • @Edge: Ah, okay, this is an Eclipse question rather than a Java or software design question. Sorry, I misunderstood that. I don't know whether Eclipse has this kind of refactoring; I'd tend to think not, but I don't use Eclipse. I'd think a good regular expression search-and-replace, or a `sed` script, should be able to get those changed for you rather than you having to do it manually. – T.J. Crowder Apr 25 '12 at 08:38
  • @SeanPatrickFloyd: I went with `letFoo`, and linked to another SO question explaining why. :-) Thanks for that. – T.J. Crowder Apr 25 '12 at 08:43
0

why are you doing this ugly thing?

Why don't you do something like

public void sometMethod(Object.. parameters)

And you can access it like

this.someMethod("a", "b", "c", "d", "e", "f"); //:)
//or
this.someMethod("a");

And to answer for your solution... you can.. using reflection...

You can access dynamically your method using reflection... link here

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Alex
  • 2,126
  • 3
  • 25
  • 47
0

If I understand you correctly, you want to automatically get from your current constructor to a no-parameter constructor with subsequent calls to the setters. I would do this by placing the setter calls into the current constructor, ensuring that they're all public, and then running the Inline Method refactoring on the constructor. Ah, but Eclipse won't let you do that. So you can write:

public static A newA(int a, int b) {
    A aa = new A();
    aa.setA(a);
    aa.setB(b);
    return aa;
}

(of course you'll have to write the empty constructor, too) and then manually replace all

a = new A(3,2);

with

a = A.newA(3,2);

and then you can inline the newA() method. Hardly worth the bother, I would think. But I don't know of a more automated way.

Carl Manaster
  • 39,912
  • 17
  • 102
  • 155