25

I'd like to have my setters so that I can chain them like:

myPojo.setX(x).setY(y);

Usually I generate setters with Eclipse but unfortunately code template for setters allows me to change only the body of the setter, not the signature.

What would be the easiest way to complete the above? Besides search-and-replace + manual editing? :)

vertti
  • 7,539
  • 4
  • 51
  • 81
  • I think the best you can do is to change the template of the method body to `${field} = ${param}; return this;` and then auto correct the resulting compiler error. – mercutio Sep 06 '12 at 07:12
  • 1
    Its hard to believe eclipse still doesn't have this as a check-box in generate setters..... – mtyson Jul 14 '16 at 21:07

8 Answers8

8

I can offer a kind of patch that however does not require any additional installations.

Go to Window/preferences/Java/Code Style/Code templates. Edit "setter body" template as following:

${field} = ${param};
return this;

Now when you run "generate getters and setters" it will create setter like:

public void setMyField(String myField) {
    this.myField = myField;
    return this;
}

This obviously cause compilation error because the method type is void. But you can strike Ctrl-F and replace all 'public void set' by public YourClassName set.

It is a patch, but it works...

AlexR
  • 114,158
  • 16
  • 130
  • 208
  • 6
    It doesn't solve the real problem. In the same manner, I could have answer to use Emacs instead of Eclipse but it would have not solve the question either. – Jérôme Radix Sep 06 '12 at 07:50
  • 2
    It does answer the question as it was originally written. Question has since been altered. – E-Riz Sep 06 '12 at 12:47
7

You could use the Editor/Templates for this purpose. To define a new Template open the Preferences Window, then Java->Editor->Templates. In this window you can define a new template and give it a name. For example:

public ${enclosing_type} setName(${argType} name) {
    this.name = name;
    return this;
}

Give it a name, e.g. settr. You can then use this template in your java code by typing 'settr' and then Ctrl-Space.

paweloque
  • 18,466
  • 26
  • 80
  • 136
  • 1
    But can you make it behave like a setter, so that `name` will be the name of any class variable? – mercutio Sep 06 '12 at 07:24
  • 7
    +1 but unfortunately this does not affect the "Source/Generate Getters and setters" – AlexR Sep 06 '12 at 07:25
  • You'll probably not fully come around this problem without writing your own plugin. – paweloque Sep 06 '12 at 07:41
  • 1
    You can replace the occurrences of `name` with `${prop:field}` which makes the solution a little more convenient, especially when you don't need the `set` in the method's name. – thorben Oct 05 '15 at 09:55
5

You might be able to use the fluent-builders-generator plugin to generate setters in the way you want to.

Keppil
  • 45,603
  • 8
  • 97
  • 119
2

My two cent on this, I (miss)use the

Preferences > Java > Code Style > Code Templates > Comments > Setter

and put there the following template:

/**
 * @param ${param} the ${bare_field_name} to set
 */
// public ${enclosing_type} ${bare_field_name}(${field_type} ${param}) {
//     ${enclosing_method}(${param});
//  return this;
// }

Benefit:

  • It can be used when generating getters setters using

    Source > Generate Getters and Setters...
    
  • It can be used when generating a single setter while typing in the editor set<start-of-fieldname> and hitting Ctrl+Space.

Drawbacks:

  • You have to tick generate comments when generating getters setters.
  • You have to remove the line comment starters, Ctrl+F // and replace with empty string.

Unfortunately, I could not find a way to uppercase the first letter of the field name which would have made using a prefix such as with possible.

A4L
  • 17,353
  • 6
  • 49
  • 70
1

Notepad++ solution:

Data:

JavaType variableName;

Search regex:

(.*) (.*);

Replace regex

public JavaType with\2\(\1 p\2\) { this.\2 = p\2; return this; }

You have to manually correct method name, since it does not uppercase the first letter of variable name.

Dariusz
  • 21,561
  • 9
  • 74
  • 114
1

I use withField naming pattern with this template

public ${enclosing_type} with${Field}(${argType} ${param}) {
    set${Field}(${param});
    return this;
}

I think it was inspired by @paweloque's answer at the time. The only differences are the added {$Field} and ${param} which are used to name the method and arguments and call the real setter generated by eclipse in the method body.

What's great about templates is that you can create your with methods using the autocomplete plus a few tabs while filing up the template's variables.

The result is something like this :

public Foo withBar(String bar)
{
    setBar(bar);
    return this;
}

Here is a screenshot to set this up in eclipse:

enter image description here

FredBoutin
  • 392
  • 3
  • 16
1

One alternative would be to use Lombok's @Setter and @Getter. Lombok enhances your classes at compile time based on some annotations. It works well on the command line and it has Eclipse support.

@Getter @Setter
public class Point {
    int x, y;

    static void test() {
        new Point().setX(1).setY(2);
    }
}

And in lombok.config :

lombok.accessors.chain=true

 

laurent
  • 674
  • 9
  • 14
0

With JavaForger you could use the template as given below to generate the setters. It does mean that you'll have to run a main method for every class that you want generate getters and setters for.

<#list fields as field>
  /**
   * Sets the ${field.name} of the {@link ${class.name}}.
   *
   * @param ${field.name} The input {@link ${field.nonPrimitiveType}}. 
   */
  public ${class.name} ${field.setter}(${field.type} ${field.name}) {
    this.${field.name} = ${field.name};
    return this;
  }
</#list>

The code below executes the template above (setters.javat) for a class called "myClass.java" and merges the generated code with the inputclass. It will override existing setters if they exist.

JavaForgerConfiguration config = JavaForgerConfiguration.builder()
  .withTemplate("setters.javat")
  .withMergeClassProvider(ClassProvider.fromInputClass(s -> s))
  .withOverride(true)
  .build();
JavaForger.execute(config, "myClass.java");

You will have to add the location of "setters.javat" with:

StaticJavaForgerConfiguration.addTemplateLocation("my/location/");

The project can be found here: https://github.com/daanvdh/JavaForger.

Daan
  • 127
  • 4