272

Is it a good or bad idea to make setters in java return "this"?

public Employee setName(String name){
   this.name = name;
   return this;
}

This pattern can be useful because then you can chain setters like this:

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

instead of this:

Employee e = new Employee();
e.setName("Jack Sparrow");
...and so on...
list.add(e);

...but it sort of goes against standard convention. I suppose it might be worthwhile just because it can make that setter do something else useful. I've seen this pattern used some places (e.g. JMock, JPA), but it seems uncommon, and only generally used for very well defined APIs where this pattern is used everywhere.

Update:

What I've described is obviously valid, but what I am really looking for is some thoughts on whether this is generally acceptable, and if there are any pitfalls or related best practices. I know about the Builder pattern but it is a little more involved then what I am describing - as Josh Bloch describes it there is an associated static Builder class for object creation.

Jonas
  • 121,568
  • 97
  • 310
  • 388
Ken Liu
  • 22,503
  • 19
  • 75
  • 98
  • 2
    Since I've seen this design pattern a while ago, I do this wherever possible. If a method doesn't explicitly need to return something to do its job, it now returns `this`. Sometimes, I even alter the function so that instead of returning a value, it operates on a member of the object, just so I can do this. It's wonderful. :) – Inversus Apr 17 '14 at 09:42
  • 7
    For telescopic setters returning self and in builders I prefer to use withName(String name) instead of setName(String name). As you pointed out a common practice and expectation for setter is to return void. "Non-standard" setters may not behave well with existing frameworks e.g. JPA entity managers, Spring, etc. – oᴉɹǝɥɔ Dec 14 '16 at 02:52
  • Please introduce line breaks before each invocation :) And configure your IDE or get a proper one if it doesn't respect this. – MauganRa Feb 23 '17 at 18:59
  • 1
    Widely used frameworks (Spring and Hibernate for instance) will strictly (at least they used to) adhere to void-setters convention – Legna Aug 08 '17 at 21:01
  • See also https://stackoverflow.com/questions/5741369/does-java-beans-setter-permit-return-this – Pino Apr 05 '19 at 12:37

27 Answers27

114

It's not bad practice. It's an increasingly common practice. Most languages don't require you to deal with the returned object if you don't want to so it doesn't change "normal" setter usage syntax but allows you to chain setters together.

This is commonly called a builder pattern or a fluent interface.

It's also common in the Java API:

String s = new StringBuilder().append("testing ").append(1)
  .append(" 2 ").append(3).toString();
cletus
  • 616,129
  • 168
  • 910
  • 942
  • 34
    It's often *used* in builders, but I wouldn't say "this is ... called a Builder pattern". – Laurence Gonsalves Aug 28 '09 at 04:31
  • 12
    It's funny to me that some of the rationale for fluent interfaces is that they make code easier to read. I could see it being more convenient to write, but it kinda strikes me as being harder to read. That's the only real disagreement I have with it. – Brent Writes Code Aug 28 '09 at 04:36
  • 1
    Probably the ultimate incarnation of fluent interfaces is LINQ – cletus Aug 28 '09 at 04:45
  • 34
    It's also known as train-wreck antipattern. Problem is that when an null-pointer exception stack trace contains a line like this, you have no idea which invocation returned null. That's not to say that chaining should be avoided at all costs, but beware of bad libraries (esp. home-brewn). – ddimitrov Mar 02 '10 at 14:49
  • @ddimitrov - The builder pattern, although it has the same appearance as a "train wreck," does not violate the Law of Demeter. Is it truly a train wreck? – Wayne Conrad Feb 02 '11 at 06:01
  • @Wayne Conrad - the law of Demeter is irrelevant here (we're not talking about middlemen) - if it throws NPE you won't know which statement caused it and that's it. There are many good examples of chained API's (Easymock/Mockito comes to mind), but I've seen some pretty horrible abominations too and they are a pain to debug and support. – ddimitrov Feb 02 '11 at 15:37
  • 19
    @ddimitrov aslong as you limit it to returning **this** it would never be a problem (only the first invokation could throw NPE) – Stefan Oct 24 '12 at 20:24
  • 1
    @BrentNash I believe the real rationale is not as much as it making the code easier to _read_ but that it makes it easier to _write_ and the authors thererfore preferring it and implicitly considering it easier to read. – Thorbjørn Ravn Andersen Feb 12 '14 at 15:38
  • 4
    **it's easier to write AND to read** assumed that you put linebreaks and indention where readability would suffer otherwise! (because it avoids redundant clutter of repeating code like `bla.foo.setBar1(...) ; bla.foo.setBar2(...)` when you could write `bla.foo /* newline indented */.setBar1(...) /* underneath previous setter */ .setBar2(...)` (can't use linebreaks in a SO comment like this :-( ... hope you get the point considering 10 such setters or more complex calls) – Andreas Covidiot Feb 06 '15 at 21:48
  • 2
    @AndreasDietrich also, this makes it possible to step through the "train" with a debugger :-D – MauganRa Feb 23 '17 at 18:51
  • "Easy to read" depends on the person. That's why we have so many different patterns ;) – Charles Wood Mar 03 '17 at 21:33
97

To summarize:

  • it's called a "fluent interface", or "method chaining".
  • this is not "standard" Java, although you do see it more an more these days (works great in jQuery)
  • it violates the JavaBean spec, so it will break with various tools and libraries, especially JSP builders and Spring.
  • it may prevent some optimizations that the JVM would normally do
  • some people think it cleans code up, others think it's "ghastly"

A couple other points not mentioned:

  • This violates the principal that each function should do one (and only one) thing. You may or may not believe in this, but in Java I believe it works well.

  • IDEs aren't going to generate these for you (by default).

  • I finally, here's a real-world data point. I have had problems using a library built like this. Hibernate's query builder is an example of this in an existing library. Since Query's set* methods are returning queries, it's impossible to tell just by looking at the signature how to use it. For example:

    Query setWhatever(String what);
    
  • It introduces an ambiguity: does the method modify the current object (your pattern) or, perhaps Query is really immutable (a very popular and valuable pattern), and the method is returning a new one. It just makes the library harder to use, and many programmers don't exploit this feature. If setters were setters, it would be clearer how to use it.

falsarella
  • 12,217
  • 9
  • 69
  • 115
ndp
  • 21,546
  • 5
  • 36
  • 52
  • 1
    The last point about immutability is very important. The simplest example is String. Java devs expect that when using methods on String they get totally new instance and not the same but modified instance. With fluent interface it would have to be mentioned in method documentation that the returned object is 'this' instead of new instance. – MeTTeO Sep 19 '15 at 09:21
  • 8
    Though I agree overall, I disagree that this violates the "do only one thing" principal. Returning `this` is hardly complex rocket science. :-) – user949300 Oct 30 '16 at 00:54
  • additional point: it also violates the Command–query separation principle. – Marton_hun May 19 '18 at 12:48
90

I prefer using 'with' methods for this:

public String getFoo() { return foo; }
public void setFoo(String foo) { this.foo = foo; }
public Employee withFoo(String foo) {
  setFoo(foo);
  return this;
}

Thus:

list.add(new Employee().withName("Jack Sparrow")
                       .withId(1)
                       .withFoo("bacon!"));

Warning: this withX syntax is commonly used to provide "setters" for immutable objects, so callers of these methods might reasonably expect them to create new objects rather than to mutate the existing instance. Maybe a more reasonable wording would be something like:

list.add(new Employee().chainsetName("Jack Sparrow")
                       .chainsetId(1)
                       .chainsetFoo("bacon!"));

With the chainsetXyz() naming convention virtually everyone should be happy.

XDS
  • 3,786
  • 2
  • 36
  • 56
qualidafial
  • 6,674
  • 3
  • 28
  • 38
  • 22
    +1 For interesting convention. I'm not going to adopt it in my own code since it seems like now you have to have a `get`, a `set` and a `with` for every class field. It's still an interesting solution, though. :) – Paul Manta Jun 21 '11 at 20:44
  • 1
    It depends on how often you call the setters. I've found that if those setters get called a lot, it's worth the extra trouble to add them since it simplifies the code everywhere else. YMMV – qualidafial Oct 24 '11 at 20:55
  • 2
    And if you added this to `Project Lombok`'s `@Getter/@Setter` annotations... that'd be fantastic for chaining. Or you could use something a lot like the `Kestrel` combinator (https://github.com/raganwald/Katy) that JQuery and Javascript fiends use. – Ehtesh Choudhury Mar 28 '12 at 19:18
  • @qualidafial - I think there's a mistake in the code. withFoo(...) should declare Employee as return value - not String. – AlikElzin-kilaka Jul 01 '13 at 11:26
  • Also, can you point to some popular libraries using this pattern? – AlikElzin-kilaka Jul 01 '13 at 11:27
  • @kilaka Thanks, I corrected the return type. As to your question, off the top of my head I don't know of any popular libraries which use this pattern. – qualidafial Jul 03 '13 at 15:36
  • What if the Java Bean is an Entity? "set", "get" prefixes cannot be omitted because they are naming convention. – emeraldhieu Jan 19 '15 at 06:28
  • Agreed. Please reread my comment, what I advocated was to include a with method that returns the self type, in addition to get and set methods. – qualidafial Jan 20 '15 at 17:14
  • Cool basic idea. I had problems with GWT AutoBeans (de)serialization with the fluent methods here and basically will use your idea in the future in this way (which is **closer - also visually/for autocompletion etc. - to the usual methods**): **`void setFoo(Foo foo); Employee setFoo$(Foo foo)`** (the `with` doesn't seem like a better idea for the con arguments to me) – Andreas Covidiot Feb 07 '15 at 12:36
  • 4
    @AlikElzin-kilaka Actually I just noticed that the java.time immutable classes in Java 8 use this pattern, e.g. LocalDate.withMonth, withYear, etc. – qualidafial Feb 11 '15 at 16:30
  • 4
    the `with` prefix is a different convention. as @qualidafial gave an example. methods prefixed with `with` should not return `this` but rather a new instance like the current instance but `with` that change. This is done to when you want your objects to be immutable. So when I see a method prefixed with `with` I assume I'll get a new object, not the same object. – tempcke Jan 13 '18 at 14:53
86

I don't think there's anything specifically wrong with it, it's just a matter of style. It's useful when:

  • You need to set many fields at once (including at construction)
  • you know which fields you need to set at the time you're writing the code, and
  • there are many different combinations for which fields you want to set.

Alternatives to this method might be:

  1. One mega constructor (downside: you might pass lots of nulls or default values, and it gets hard to know which value corresponds to what)
  2. Several overloaded constructors (downside: gets unwieldy once you have more than a few)
  3. Factory/static methods (downside: same as overloaded constructors - gets unwieldy once there is more than a few)

If you're only going to set a few properties at a time I'd say it's not worth returning 'this'. It certainly falls down if you later decide to return something else, like a status/success indicator/message.

Tom Clift
  • 2,365
  • 23
  • 20
  • 2
    well, generally you don't return anything from a setter anyway, by convention. – Ken Liu Aug 28 '09 at 04:39
  • 18
    Maybe not to start with, but a setter doesn't necessarily keep its original purpose. What used to be a variable might change into a state that encompasses several variables or have other side effects. Some setters might return a previous value, others might return a failure indicator if failure is too common for an exception. That raises another interesting point though: what if a tool/framework you're using doesn't recognise your setters when they have return values? – Tom Clift Aug 28 '09 at 04:54
  • 13
    @Tom good point, doing this breaks the "Java bean" convention for getters and setters. – Andy White Aug 28 '09 at 04:57
  • 2
    @TomClift Does breaking "Java Bean" convention cause any issues? Are libraries that use the "Java Bean" convention looking at the return type or just the method parameters and the method name. – Theo Briscoe Dec 05 '13 at 14:30
  • unfortunately I am working in a data-bean-centric (DTOs, DAOs) env this way and now I **can't benefit from the *AutoBean* (https://code.google.com/p/google-web-toolkit/wiki/AutoBean#Quickstart) functionality that can't handle this non-Bean-Standard out-of-the-box**. So I am afraid to **loose the advantage of less boilerplate code** here :-(. But maybe there is a way with it ... I'll see. – Andreas Covidiot Feb 06 '15 at 21:41
  • 3
    that is why the Builder pattern exists, setters should not return something, instead, create a builder if its needed looks better and takes less code :) – RicardoE Apr 17 '15 at 22:45
  • you can have special setter which could take a Map of properties (name and values). Then, inside the method you can use reflection to invoke appropriate setters. This approach may not work when you have some overloaded setters and benefit of compile time checking is also lost. – Bimalesh Jha Jul 07 '16 at 14:55
  • For me it's seems the name of the function lies if I am return with anything. If it's returns with the object, then the name of this should be `setPropertyAndGetObject();` Set has one thing, to set a property. Of course I do not need to know how the setter is implements this set for example `$A->setFullName($firstName, $lastName);` can do some logic for example, in different countries the last name is the first and first name is the second. But it do only one thing: sets the fullname. – vaso123 Mar 08 '17 at 13:01
  • @vaso123 I feel your pain...But if the alternative is to have a mega-constructor I can live with it... Anyway your example is not so clear for mee:: when you, me, or anyone ears about 'setter' thinks about 'getters and setters', and no about 'calculate the correct strategy to create a value and set it': Your example should be: setFullName(calcFullName(firstName, lastName)). For me, having Setters an Getters a clear definition in my mind, the question should be: would the fact of returning 'this' in the setter change that definition in a dramatic way? – inigoD Feb 15 '18 at 10:03
  • Returning `this` is fundamental to the `Builder` pattern. But, returning `this` is also, by design a stateful operation. There is no one-size-fits-all. Favor immutability. The whole point of a builder (usually) is to make building an immutable object failsafe – Christian Bongiorno Aug 20 '18 at 21:55
26

If you don't want to return 'this' from the setter but don't want to use the second option you can use the following syntax to set properties:

list.add(new Employee()
{{
    setName("Jack Sparrow");
    setId(1);
    setFoo("bacon!");
}});

As an aside I think its slightly cleaner in C#:

list.Add(new Employee() {
    Name = "Jack Sparrow",
    Id = 1,
    Foo = "bacon!"
});
Luke Quinane
  • 16,447
  • 13
  • 69
  • 88
  • 17
    double brace initialization may have problems with equals because it creates an anonymous inner class; see http://www.c2.com/cgi/wiki?DoubleBraceInitialization – Csaba_H Aug 28 '09 at 05:59
  • @Csaba_H Clearly that problem is the fault of the person who bungled the `equals` method. There are very clean ways to deal with anonymous classes in `equals` if you know what you are doing. – AJMansfield Jan 24 '14 at 20:07
  • 1
    creating a new (anonymous) class just for that? for every instance? – user85421 Aug 05 '19 at 12:39
  • **Captain** Jack Sparrow – pro100tom Jun 30 '22 at 17:49
11

It not only breaks the convention of getters/setters, it also breaks the Java 8 method reference framework. MyClass::setMyValue is a BiConsumer<MyClass,MyValue>, and myInstance::setMyValue is a Consumer<MyValue>. If you have your setter return this, then it's no longer a valid instance of Consumer<MyValue>, but rather a Function<MyValue,MyClass>, and will cause anything using method references to those setters (assuming they are void methods) to break.

Steve K
  • 4,863
  • 2
  • 32
  • 41
9

I don't know Java but I've done this in C++. Other people have said it makes the lines really long and really hard to read, but I've done it like this lots of times:

list.add(new Employee()
    .setName("Jack Sparrow")
    .setId(1)
    .setFoo("bacon!"));

This is even better:

list.add(
    new Employee("Jack Sparrow")
    .Id(1)
    .foo("bacon!"));

at least, I think. But you're welcome to downvote me and call me an awful programmer if you wish. And I don't know if you're allowed to even do this in Java.

Carson Myers
  • 37,678
  • 39
  • 126
  • 176
  • The "even better" does not lend well to the Format Source code functionality available in modern IDE's. Unfortunately. – Thorbjørn Ravn Andersen Aug 28 '09 at 06:13
  • you're probably right... The only auto-formatter I have used is emacs' auto indenting. – Carson Myers Aug 29 '09 at 00:21
  • 2
    Source code formatters can be coerced with a simple // after each method call in the chain. It uglies up your code a little, but not as much having your vertical series of statements reformatted horizontally. – qualidafial Dec 20 '10 at 19:40
  • @qualidafial You don't need `//` after each method if you configure your IDE not to join already wrapped lines (e.g. Eclipse > Properties > Java > Code Style > Formatter > Line Wrapping > Never join already wrapped lines). – DJDaveMark Jan 16 '19 at 08:39
8

It's not a bad practice at all. But it's not compatiable with JavaBeans Spec.

And there is a lot of specification depends on those standard accessors.

You can always make them co-exist to each other.

public class Some {
    public String getValue() { // JavaBeans
        return value;
    }
    public void setValue(final String value) { // JavaBeans
        this.value = value;
    }
    public String value() { // simple
        return getValue();
    }
    public Some value(final String value) { // fluent/chaining
        setValue(value);
        return this;
    }
    private String value;
}

Now we can use them together.

new Some().value("some").getValue();

Here comes another version for immutable object.

public class Some {

    public static class Builder {

        public Some build() { return new Some(value); }

        public Builder value(final String value) {
            this.value = value;
            return this;
        }

        private String value;
    }

    private Some(final String value) {
        super();
        this.value = value;
    }

    public String getValue() { return value; }

    public String value() { return getValue();}

    private final String value;
}

Now we can do this.

new Some.Builder().value("value").build().getValue();
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
  • 2
    My edit got rejected, but your Builder example is not correct. First, .value() does not return anything, and it doesn't even set the `some` field. Secondly, you should add a safeguard and set `some` to `null` in build() so `Some` is truly immutable, otherwise you could call `builder.value()` on the same Builder instance again. And Lastly, yes you have a builder, but your `Some` still has a public constructor, meaning you do not openly advocate the use of the Builder, i.e. the user knows not of it other than by trying out or searching for a method to set a custom `value` at all. – Adowrath Mar 30 '17 at 20:12
  • @Adowrath if the answer is incorrect, you should write your own answer, not try and edit someone else's into shape – CalvT Aug 03 '17 at 11:37
  • @CalvT븃So I should leave wrong information there when it just needs a little bit of editing? It's not "editing into shape", but correcting the small mistakes he made. Also, his Builder example is an extension on a normal answer, and would not warrant an altogether own answer by me. – Adowrath Aug 03 '17 at 11:49
  • 1
    @JinKwon Great. Thanks! And sorry if I seemed rude before. – Adowrath Aug 18 '17 at 05:56
  • 1
    @Adowrath Please feel free for any additional comments for enhancements. FYI, I'm not the one who rejected your edit. :) – Jin Kwon Aug 18 '17 at 06:01
  • 1
    I know, I know. ^^ And thanks for the new version, that now provides a real mutable "Immutable-Some" builder. And it's a more clever solution than my edit attempts which, in comparison, cluttered the code. – Adowrath Aug 18 '17 at 22:12
7

At least in theory, it can damage the optimization mechanisms of the JVM by setting false dependencies between calls.

It is supposed to be syntactic sugar, but in fact can create side effects in the super-intelligent Java 43's virtual machine.

That's why I vote no, don't use it.

Paul Vargas
  • 41,222
  • 15
  • 102
  • 148
Marian
  • 2,617
  • 1
  • 16
  • 13
  • 10
    Interesting...could you expand on this a bit? – Ken Liu Aug 28 '09 at 04:51
  • Agreed, I'd like to know more about how this can affect optimization – Carson Myers Aug 28 '09 at 05:06
  • 3
    Just think about how superscalar processors deal with parallel execution. The object to execute the second `set` method on is dependent on the first `set` method although it is known by the programmer. – Marian Aug 28 '09 at 21:51
  • 2
    I still don't follow. If you set Foo and then Bar with two separate statements, the object for which you're setting Bar has a different state than the object for which you're setting Foo. So the compiler couldn't parallelize those statements, either. At least, I don't see how it could without introducing an unwarranted assumption.(Since I have no idea about it, I won't deny that Java 43 does in fact do the parallelization in the once case but not the other and introduce the unwarranted assumption in the one case but not the other). – masonk Feb 27 '11 at 01:18
  • @masonk: Perhaps something like this: `obj.modifyList(aList).modifyList(anotherList)`, where `modifyList` does not modify `this`, yet needs to know what `this` is. – Thomas Eding Aug 09 '11 at 00:46
  • 13
    If you don't know, test. `-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining` The java7 jdk definitely inlines chained methods, and does around the same number of iterations it takes to mark void setters as hot and inline them too. Methinks you underestimate the power of the JVM's opcode pruning algorithms; if it knows you are returning this, it will skip the jrs (java return statement) opcode and just leave this on the stack. – Ajax Feb 01 '13 at 15:11
  • But one should really consider if optimization is an issue for his code. Almost all code I wrote in my career was not to be run superfast or something, but should rather be understandable and fault free. So I would argue that the majority of code/coders need not to be extremely concerned with speed rather than maintainability which also includes readability. Java itself is a very good example that it was one of the slowest lang. some years back, but still had been adopted almost everywhere because speed will incr. on the hard and softw.-side anyways, but maintainability is much more important. – Andreas Covidiot Feb 24 '17 at 09:06
  • 1
    Andreas, I agree but problems appear when you have layer upon layer of inefficient code. 99% of the time you should code for clarity which gets said a lot around here. But there are also times when you need to be realistic and use your years of experience to prematurely optimize in a general architectural sense. – LegendLength Jul 14 '17 at 20:01
  • What I'm curious about is if optimization breaks down in a more complex "chain" setter with multiple return branches of "this." Will have to test once I get the chance... – Philip Guin May 09 '20 at 22:38
7

Because it doesn't return void, it's no longer a valid JavaBean property setter. That might matter if you're one of the seven people in the world using visual "Bean Builder" tools, or one of the 17 using JSP-bean-setProperty elements.

Ken
  • 814
  • 4
  • 3
5

This scheme (pun intended), called a 'fluent interface', is becoming quite popular now. It's acceptable, but it's not really my cup of tea.

Noon Silk
  • 54,084
  • 6
  • 88
  • 105
5

If you use the same convention in whole applicaiton it seems fine.

On the oher hand if existing part of your application uses standard convention I'd stick to it and add builders to more complicated classes

public class NutritionalFacts {
    private final int sodium;
    private final int fat;
    private final int carbo;

    public int getSodium(){
        return sodium;
    }

    public int getfat(){
        return fat;
    }

    public int getCarbo(){
        return carbo;
    }

    public static class Builder {
        private int sodium;
        private int fat;
        private int carbo;

        public Builder sodium(int s) {
            this.sodium = s;
            return this;
        }

        public Builder fat(int f) {
            this.fat = f;
            return this;
        }

        public Builder carbo(int c) {
            this.carbo = c;
            return this;
        }

        public NutritionalFacts build() {
            return new NutritionalFacts(this);
        }
    }

    private NutritionalFacts(Builder b) {
        this.sodium = b.sodium;
        this.fat = b.fat;
        this.carbo = b.carbo;
    }
}
Marcin Szymczak
  • 11,199
  • 5
  • 55
  • 63
  • 1
    This is exactly what the Builder pattern was designed to fix. It doesn't break lambdas in Java 8, it doesn't break finicky JavaBeans tools, and it doesn't cause any optimization issues in JVM (since the object only exists during instantiation). It also solves the "way too many constructors" problem that you get by simply not using builders, as well as eliminating heap pollution from double-brace anonymous classes. – ndm13 Dec 29 '17 at 20:26
  • Interesting point - I'm noticing that if almost nothing in your class is immutable, though (e.g. a highly configurable GUI), then you can probably avoid Builder altogether. – Philip Guin May 09 '20 at 22:40
4

Paulo Abrantes offers another way to make JavaBean setters fluent: define an inner builder class for each JavaBean. If you're using tools that get flummoxed by setters that return values, Paulo's pattern could help.

entpnerd
  • 10,049
  • 8
  • 47
  • 68
Jim Ferrans
  • 30,582
  • 12
  • 56
  • 83
  • 2
    @cdunn2001, [use wayback machine, Luke](http://web.archive.org/web/20101018140949/http://www.pabrantes.net/blog/space/start/2007-11-14/1) – msangel Jan 05 '14 at 18:52
3

I'm in favor of setters having "this" returns. I don't care if it's not beans compliant. To me, if it's okay to have the "=" expression/statement, then setters that return values is fine.

Monty Hall
  • 31
  • 1
3

This particular pattern is called Method Chaining. Wikipedia link, this has more explanation and examples of how it's done in various programming languages.

P.S: Just thought of leaving it here, since I was looking for the specific name.

capt.swag
  • 10,335
  • 2
  • 41
  • 41
2

Yes, I think it's a good Idea.

If I could add something, what about this problem :

class People
{
    private String name;
    public People setName(String name)
    {
        this.name = name;
        return this;
    }
}

class Friend extends People
{
    private String nickName;
    public Friend setNickName(String nickName)
    {
        this.nickName = nickName;
        return this;
    }
}

This will work :

new Friend().setNickName("Bart").setName("Barthelemy");

This will not be accepted by Eclipse ! :

new Friend().setName("Barthelemy").setNickName("Bart");

This is because setName() returns a People and not a Friend, and there is no PeoplesetNickName.

How could we write setters to return SELF class instead of the name of the class ?

Something like this would be fine (if the SELF keyword would exist). Does this exist anyway ?

class People
{
    private String name;
    public SELF setName(String name)
    {
        this.name = name;
        return this;
    }
}
Baptiste
  • 364
  • 2
  • 5
  • 1
    There are a few other Java compilers besides Eclipse that won't accept that :). Basically, you're running fowl of the Java type system (which is static, not dynamic like some scripting languages): you'll have to cast what comes out of setName() to a Friend before you can setNickName() on it. So, unfortunately, for inheritance hierarchies this eliminates much of the readability advantage and renders this otherwise potentially-useful technique not-so-useful. – Cornel Masson Jun 04 '12 at 09:39
  • 6
    Use generics. class Chainable { public Self doSomething(){return (Self)this;} } It's not technically type safe (it will class cast if you implement the class with a Self type you cannot be case to), but it is correct grammar, and subclasses will return their own type. – Ajax Feb 01 '13 at 15:17
  • In addition: This "SELF" that Baptiste is using is called a self type, not present in many languages (Scala is really the only one I can think of right now), where as Ajax's use of Generics is the so-called "Curiously recurring template pattern", which tries to cope with a lack of the self type, but it's got some drawbacks: (from `class C>`, which is safer than a plain `S extends C`. a) If `A extends B`, and `B extends C`, and you have an A, you only know that a B is returned unless A overrides each and every method. b) You can't denote a local, non-raw `C>>>>`. – Adowrath Aug 19 '17 at 19:49
2

I used to prefer this approach but I have decided against it.

Reasons:

  • Readability. It makes the code more readable to have each setFoo() on a separate line. You usually read the code many, many more times than the single time you write it.
  • Side effect: setFoo() should only set field foo, nothing else. Returning this is an extra "WHAT was that".

The Builder pattern I saw do not use the setFoo(foo).setBar(bar) convention but more foo(foo).bar(bar). Perhaps for exactly those reasons.

It is, as always a matter of taste. I just like the "least surprises" approach.

Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
  • 2
    I agree on the side effect. Setters that return stuff violates their name. You are setting foo, but you get an object back? Is this a new object or have I altered the old? – crunchdog Aug 28 '09 at 05:52
1

On first sight: "Ghastly!".

On further thought

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

is actually less error prone than

Employee anEmployee = new Employee();
anEmployee.setName("xxx");
...
list.add(anEmployee);

So quite interesting. Adding idea to toolbag ...

djna
  • 54,992
  • 14
  • 74
  • 117
  • 1
    No, it's still ghastly. From a maintenance perspective, the latter is better because it's easier to read. Additionally, automated code checkers like CheckStyle will enforce lines to be 80 characters by default - the code would get wrapped anyway, compounding the readability/maintainence issue. And finally - it's Java; there's no benefit to writing everything on a single line when it's going to be compiled to byte code anyway. – OMG Ponies Aug 28 '09 at 04:52
  • 1
    personally, I think the former is easier to read, especially if you are creating several objects this way. – Ken Liu Aug 28 '09 at 04:53
  • @Ken: Code a method. Write one copy in fluent format; another copy in the other. Now give the two copies to a couple of people, and ask which one they find easier to read. Faster to read, faster to code. – OMG Ponies Aug 28 '09 at 04:57
  • Like most tools, it can be easy to overuse. JQuery is oriented around this technique and is thus prone to long call chains which I've found actually impairs readability. – staticsan Aug 28 '09 at 05:18
  • 2
    It would be alright if there were linebreaks before each dot and indented. Then, it'd be as readable as the second version. Actually more, because there is no redundant `list` at the beginning. – MauganRa Feb 23 '17 at 18:53
1

In general it’s a good practice, but you may need for set-type functions use Boolean type to determine if operation was completed successfully or not, that is one way too. In general, there is no dogma to say that this is good or bed, it comes from the situation, of course.

Narek
  • 38,779
  • 79
  • 233
  • 389
  • 3
    How about using exceptions to indicate error condition? Error codes can be easily ignored as many C programmers painfully have learned. Exceptions can bubble up the stack to the point where they can be handled. – ddimitrov Mar 02 '10 at 14:59
  • Exceptions are preferable usually, but error codes are useful too when you can't use exceptions. – Narek Nov 15 '17 at 17:09
  • 1
    Hi @Narek, perhaps you could elaborate in what cases it is preferable to use error codes in setters, rather than exceptions and why? – ddimitrov Jan 16 '18 at 08:37
0

From the statement

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

i am seeing two things

1) Meaningless statement. 2) Lack of readability.

LiraNuna
  • 64,916
  • 15
  • 117
  • 140
Madhu
  • 5,686
  • 9
  • 37
  • 53
0

I have been making my setters for quite a while and the only real issue is with libraries that stick with the strict getPropertyDescriptors to get the bean reader/writer bean accessors. In those cases, your java "bean" will not have the writters that you would expect.

For example, I have not tested it for sure, but I would not be surprised that Jackson won't recognizes those as setters when creating you java objects from json/maps. I hope I am wrong on this one (I will test it soon).

In fact, I am developing a lightweight SQL centric ORM and I have to add some code beyong getPropertyDescriptors to recognized setters that returns this.

Jeremy Chone
  • 3,079
  • 1
  • 27
  • 28
0

This may be less readable

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!")); 

or this

list.add(new Employee()
          .setName("Jack Sparrow")
          .setId(1)
          .setFoo("bacon!")); 

This is way more readable than:

Employee employee = new Employee();
employee.setName("Jack Sparrow")
employee.setId(1)
employee.setFoo("bacon!")); 
list.add(employee); 
falsarella
  • 12,217
  • 9
  • 69
  • 115
Scott
  • 17
  • 1
0

Long ago answer, but my two cents ... Its fine. I wish this fluent interface were used more often.

Repeating the 'factory' variable does not add more info below:

ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(Foo.class);
factory.setFilter(new MethodFilter() { ...

This is cleaner, imho:

ProxyFactory factory = new ProxyFactory()
.setSuperclass(Properties.class);
.setFilter(new MethodFilter() { ...

Of course, as one of the answers already mentioned, the Java API would have to be tweaked to do this correctly for some situations, like inheritance and tools.

Josef.B
  • 942
  • 8
  • 16
0

It is better to use other language constructs if available. For example, in Kotlin, you would use with, apply, or let. If using this approach, you won't really need to return an instance from your setter.

This approach allows your client code to be:

  • Indifferent to the return type
  • Easier to maintain
  • Avoid compiler side effects

Here are some examples.

val employee = Employee().apply {
   name = "Jack Sparrow"
   id = 1
   foo = "bacon"
}


val employee = Employee()
with(employee) {
   name = "Jack Sparrow"
   id = 1
   foo = "bacon"
}


val employee = Employee()
employee.let {
   it.name = "Jack Sparrow"
   it.id = 1
   it.foo = "bacon"
}
Steven Spungin
  • 27,002
  • 5
  • 88
  • 78
0

If I'm writing an API, I use "return this" to set values that will only be set once. If I have any other values that the user should be able to change, I use a standard void setter instead.

However, it's really a matter of preference and chaining setters does look quite cool, in my opinion.

0

I agree with all posters claiming this breaks the JavaBeans spec. There are reasons to preserve that, but I also feel that the use of this Builder Pattern (that was alluded to) has its place; as long as it is not used everywhere, it should be acceptable. "It's Place", to me, is where the end point is a call to a "build()" method.

There are other ways of setting all these things of course, but the advantage here is that it avoids 1) many-parameter public constructors and 2) partially-specified objects. Here, you have the builder collect what's needed and then call its "build()" at the end, which can then ensure that a partially-specified object is not constructed, since that operation can be given less-than-public visibility. The alternative would be "parameter objects", but that IMHO just pushes the problem back one level.

I dislike many-parameter constructors because they make it more likely that a lot of same-type arguments are passed in, which can make it easier to pass the wrong arguments to parameters. I dislike using lots of setters because the object could be used before it is fully configured. Further, the notion of having default values based on previous choices is better served with a "build()" method.

In short, I think it is a good practice, if used properly.

Javaneer
  • 41
  • 5
-4

Bad habit: a setter set a getter get

what about explicitly declaring a method, that does it for U

setPropertyFromParams(array $hashParamList) { ... }
  • not good for auto-completion and refactoring and readability anb boilerplate code – Andreas Covidiot Feb 24 '17 at 09:13
  • Because: 1) You have to remember the order or read it from docs, 2) you loose all compile-time type safety, 3) you have to cast the values (this and 2) is of course a non-problem in a dynamic language of course), 4) you can **not** extend this usefully other than checking the array-length on every invocation, and 5) **if** you change anything, be it order or even the existence of certain values, you can **not** check that neither runtime nor compile timewithout doubt **at all**. With setters: 1), 2), 3): Not a problem. 4) Adding new methods does not break anything. 5) explicit error message. – Adowrath Mar 29 '17 at 17:14