Argument Accumulator

How to NameArguments used in a constructor.

Typical usage:

 Widget = new WidgetCreator()
     .settingThis()
     .andThat(foo)
     .squidgability(0.9)
     .create();

This is a neat idea written up by DavidHarvey at http://www.davethehat.com/articles/aa.pdf

Bjarne Stroustrup also suggests this idiom in a C++ book (I think TheDesignAndEvolutionOfCpp [FixMe]). I use it a fair bit in CeePlusPlus, it strikes me as neat, although obviously not for compulsory arguments as there is no (simple!) way to force the client to set all the right things.

The drawback of this approach is that it does not work with inheritance because Java does not allow methods to be overridden with covariant return types.

E.g. you would like to be able to do this...

    class Widget { ... }
    class WidgetCreator {
        WidgetCreator squidgability( double d ) { ... }
        ...
    }

class Gadget extends Widget { ... } class GadgetCreator extends WidgetCreator { GadgetCreator squidgability( double d ) { ... } ... }

...but you can't. J2SE 1.5 will allow covariant return types! Yay! --TimMoore
PeterNorvig, in his Java Infrequently Asked Questions page at http://www.norvig.com/java-iaq.html#constructors, suggests using anonymous subclasses. I'll paraphrase:

Given a class with 6 instance variables a--f, you can avoid writing 64 constructors by using set methods as in the example above (but this won't work with inheritance). It also is not JavaBean-compliant, if you care about such things.

 public C setA(int val) { a = val; return this; }
 ...
 C x = new C().setA(1).setC(3).setE(5);

Or, you could create an anonymous subclass with a non-static initializer block with code like:

 C x = new C() {{ a = 1; c = 3; e = 5; }};

Of course, a--f need to be public. I suppose you could compromise:

 public void setA(int val) { a = val;}
 ...
 C x = new C() {{ setA(1); setC(3); setE(5); }};

Peter Norvig also suggests that if you reject this solution you use C++ for its optional arguments, or you use LISP for its keyword arguments.

One problem I realized with this is that it interferes with a common method of WritingEqualsMethods. That method requires you to use getClass() to check that the argument is of the same class as this to make equals() symmetric.

An example of applying this method is:

  // In class C
  public boolean equals(Object o) {
    if (this.getClass() == o.getClass()) {
      C c2 = (C) o;
      return (a == c2.a) && (b == c2.b) && ...;
    } else {
      return false;
    }
  }

However, Norvig's method causes strange results here:

  C x = new C() {{ setA(1); setC(3); setE(5); }};
  C y = new C();
  y.setA(1);
  y.setC(3);
  y.setE(5);
  boolean b = x.equals(y); // Always false.

I'm not sure what the best method to use is.

--EricJablow

Very neat! But this creates even more additional classes, so could cause a problem for applet writers.--AnonymousDonor

Yes, it increases the cost of deployment. Also, objects created this way cannot usefully be serialized. Since any object created in this way is the unique instance of an otherwise inaccessible class, it cannot be deserialized from a stream. I am not sure I would ever use this idiom.--EricJablow


My main complaint is that an ArgumentAccumulator is not standard, and thus more difficult to read. People expect setX methods to return void, and I'd rather not violate that assumption.
Perhaps better approach is to use BuilderPattern. That way you can check that all mandatory arguments are actually set and it allows building ImmutableObjects.
JavaIdioms (...not that it can't be used in other languages.)
EditText of this page (last edited January 10, 2005)
FindPage by browsing or searching

This page mirrored in JavaIdioms as of April 29, 2006