On Wed, 7 Aug 2013 13:39:41 -0700, Ted Dunning wrote:
This is often dealt with by using builder classes and not putting all
the
fluent methods on the objects being constructed.
Builders seem fine when no inheritance is involved: all fields are
duplicated (and mutable) in the builder, then an immutable instance
is created from the contents of the builder instance.
But when fields are spread in several classes of a hierarchy, how to
combine the respective builders?
Having one builder at the bottom of the hierarchy would work, but
defeats the purpose of initializing the field with the fluent method
defined in the class where the field is declared.
The other way to deal with this is to use a covariant return type.
For
instance, there is no guarantee that Pattern.compile returns any
particular
class other than that it returns a sub-class of Pattern.
The here purpose is the fluent method always returns the actual type.
This can be nicely solved with generics (cf. "self-type") provided that
the "this" reference is retained (which is not true with immutability).
Do you have a specific example of the problem you are alluding to?
Yes: see the classes in "o.a.c.m.fitting.leastsquares".
I strongly suspect that a lot of the code dedicated to the fluent API
could be removed if immutability is dropped.
Gilles
On Wed, Aug 7, 2013 at 11:23 AM, Gilles
<gil...@harfang.homelinux.org>wrote:
Hi.
It seems that each two of those concepts are at odds with
the third one.
E.g. you can have a fluent API and immutability, but this
then prevents you from defining fluent API methods in a base
class because immutability requires creating a new object
(but the base class cannot know how to "build" a subclass).
Dropping immutability would allow to define "withXxx" at the
hierarchy level where they belong because the fluent methods
modify instance fields (and return an existing "this").
Whereas keeping immutability requires that all "withXxx" are
always redefined at the bottom level of the hierarchy.
Also, if a base class is "abstract", no fluent method can be
defined in it, since it cannot be instantiated. This also
leads to the situation where the (re)initialization of fields
that belong to the base class must be delegated to "withXxx"
methods in all the subclasses.
Thus, in this particular case, immutability entails code
duplication.
I wonder whether it would be possible to have the best of all
worlds by
1. dropping immutability of the instance fields,
2. requiring that all classes participating in the fluent API
implement a copy constructor,
3. requiring that all non abstract classes implement a "copy"
method (whose contract is to return a fresh copy).
Hence, code that would like to ensure that it is the sole owner
of an object would be able to call the "copy" method on a
mutable instance that would have been constructed with the
fluent API.
[One a side note: that proposal would also seem to reduce the
overhead (however small that may be) of creating a new object
for each modification, as well as allow usage in situations where
creating a new instance would be undesirable e.g.:
Applying a "withXxx" method on an object stored in a collection
would create a local instance, and require that it be assigned back
into the collection, preventing a language construct such as
"foreach" loops.]
I know that dropping immutability seems a step backwards from what
were trying to achieve in Commons Math but it seems that we must
let go of something (and security could be retained by unit tests
that check the contract of "copy")
If I'm missing something obvious, please let me know!
Gilles
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org