Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #11899
| From | Eric Sosman <esosman@ieee-dot-org.invalid> |
|---|---|
| Newsgroups | comp.lang.java.programmer |
| Subject | Re: Question about Effective Java |
| Date | 2012-02-09 21:08 -0500 |
| Organization | A noiseless patient Spider |
| Message-ID | <jh1u7n$691$1@dont-email.me> (permalink) |
| References | <Xns9FF4833D32E5Ajpnasty@94.75.214.39> <QrudnRBcJtTn26nSnZ2dnUVZ_qSdnZ2d@earthlink.com> <Xns9FF4C853AB5ACjpnasty@94.75.214.39> |
On 2/9/2012 7:40 PM, Novice wrote:
> Patricia Shanahan<pats@acm.org> wrote in
> news:QrudnRBcJtTn26nSnZ2dnUVZ_qSdnZ2d@earthlink.com:
>
>> On 2/9/2012 9:54 AM, Novice wrote:
>>> I'm trying to understand the example on page 14 of Effective Java by
>>> Joshua Bloch (Second Edition). I hope someone here can help.
>> ...
>>> public Builder sodium(int val) {
>>> this.sodium = val;
>>> return this;
>>> }
>> ...:
>>> 1. I understand that a NutritionFacts could conceivably be just a
>>> servingSize and a number of servings. All of the other values are
>>> optional on an individual basis: any one or more of them could be
>>> there but don't need to be. Any value that is omitted takes a default
>>> (of zero in this example). But why are the methods calories(), fat(),
>>> carbohydrate() and sodium() each returning Builder? They aren't
>>> constructors and they only deal with one data value, fat or calories
>>> or whatever, but they apparently return a complete Builder.
>>>
>>
>> Don't think in terms of "return a complete Builder". Java programs do
>> not, and cannot, pass objects around as method arguments or results.
>> sodium really returns a Builder reference. A reference can either be
>> null or be a pointer to an object of appropriate class.
>>
>> Inside sodium, "this" is a pointer to the current object. Returning it
>> allows chaining of several method calls.
>>
> I'll have to mull that over for a bit and consider the implications.
>
> At first glance it seems simple enough; in any other class, "this" refers
> to an instance of the class that contains the "this", just like we see
> here. But I'm not used to seeing several methods in a class all return
> "this".
Analogies are never perfect, but often helpful. So, imagine a
group of friends ordering pizza: They've got a slip of paper listing
possible toppings, and they're going to put check marks next to the
items they want. "Pepperoni," says George, "gotta have pepperoni,"
making his mark on the paper and passing it to Gina. "Mushrooms
make my breath fresher," she says, adding her mark and passing the
paper along to Gail. She opts for extra cheese and hands the paper
to Guy, who's worried about his weight and says "Sounds good, let's
just go with these three." He passes the paper over the counter to
Guido, who makes them a pluperfectly personalized pizza.
Now, what do the friends pass among themselves during this
colloquy? Do they pass the pizza? No, it hasn't even been made
yet. Do they pass their chosen ingredients? No, George doesn't
have a handful of pepperoni, nor does Gina have mushrooms nor Gail
extra cheese, and Guy doesn't have plenty of nothing. What they
pass is the slip of paper, the specification of the pizza they would
like Guido to build for them.
... and that's very much like what's going on with Builder and
NutritionFacts. The friends "make marks on" a Builder, then hand
the Builder to Guido, who makes them a NutritionFacts built to its
specification.
That's the idea; now to the returning of "this". It's just a
convenience, really. Imagine that all those Builder methods were
"void", returning nothing at all. Then you'd write
NutritionFacts.Builder b = new NutritionFacts.Builder(300, 4);
b.calories(950);
b.sodium(800);
b.carbohydrate(1025);
NutritionFacts facts = b.build();
That is, you'd use the variable "b" to hold a reference to the
Builder while you "make your marks" on it. Eventually, you call
its build() method to "hand it to Guido" and get a pizza -- er,
that is, a NutritionFacts -- made to order. This would work just
fine, and there's nothing fundamentally wrong with it.
But if each of the Builder method returns a reference to the
Builder it has just "marked" things can be written a little more
compactly:
NutritionFacts facts =
new NutritionFacts.Builder(300, 4)
.calories(950)
.sodium(800)
.carbohydrate(1025)
.build();
Observe that you no longer need the "b" variable: The "new" creates
a Builder and produces a reference to it, the calories() method
modifies that Builder and returns a reference that the sodium()
method can use, ..., until eventually the build() method takes all
the information stored in the Builder and uses it to generate a
Pizza -- er, that is, a NutritionFacts. Since there's no "b" to
refer to the Builder, it becomes eligible for garbage collection
as soon as its fulfilled its purpose, namely, specifying what's
wanted in the new NutritionFacts.
In short, the returning of "this" enables a convenience, but
is not truly fundamental to the pattern of using a builder of some
kind to hold the parameters for a hidden constructor.
> I'm also not used to named classes nested within classes. (I'm
> familiar with anonymous inner classes like window listeners and with
> putting additional named classes within the same source file in a
> sequential fashion but putting a named class within another is still
> feels a little odd.)
You'll get used to it. The pattern works even if the builder
class is completely separate from the built class -- consider, for
example, StringBuilder and String. (And note how StringBuilder's
append() method, for instance, returns a reference to the same
StringBuilder that the append() modified.)
> I'll post back if I can't make my peace with this slightly exotic
> technique ;-)
You'll get used to it. (Is there an echo in here?)
--
Eric Sosman
esosman@ieee-dot-org.invalid
Back to comp.lang.java.programmer | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
Question about Effective Java Novice <novice@example..com> - 2012-02-09 17:54 +0000
Re: Question about Effective Java markspace <-@.> - 2012-02-09 10:39 -0800
Re: Question about Effective Java Novice <novice@example..com> - 2012-02-10 00:07 +0000
Re: Question about Effective Java markspace <-@.> - 2012-02-09 16:42 -0800
Re: Question about Effective Java Patricia Shanahan <pats@acm.org> - 2012-02-09 14:19 -0800
Re: Question about Effective Java Novice <novice@example..com> - 2012-02-10 00:40 +0000
Re: Question about Effective Java Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-02-09 21:08 -0500
Re: Question about Effective Java Lew <lewbloch@gmail.com> - 2012-02-10 09:01 -0800
Re: Question about Effective Java "John B. Matthews" <nospam@nospam.invalid> - 2012-02-10 11:59 -0500
csiph-web