Is it bad practice to make a setter return "this"?
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:
- One mega constructor (downside: you might pass lots of nulls or default values, and it gets hard to know which value corresponds to what)
- Several overloaded constructors (downside: gets unwieldy once you have more than a few)
- 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.
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();
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.
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.