Maven 2 on the right track… Reason to move to WI: Kill Cats
Apr 12

Caller context and list.add(..).add(..).add(..)

Java, Perl, Tech Add comments

One of the first things that bugged me about Java when I first started to use it was a small thing. Why didn’t add() return the list (or Vector back then) so I could chain the calls together.

I wanted to be able to:

Vector v = new Vector().add(”foo”).add(”bar);

The same goes for having chained set* methods:

foo.setA(a).setB(b)

We see this used, especially in certain packages such as Hibernate.

One feature that I liked in Perl was the ability to know about the callers context:

my $scalar = @list; # or function which returns a list

is very different to:

my ($element) = @list; # or function which returns a list

Sometimes I would love to do the same in this world and say “If the caller of my set method wants the object back, give it, else we are in void world and that is fine too”.

Of course, I don’t think this would happen :)

Another way to make me a little more happy would be to give me named parameters, but that doesn’t give me the same power.

12 Responses to “Caller context and list.add(..).add(..).add(..)”

  1. Cedric Says:

    Interestingly, the first feature would give you the second one for free.

    new Window().color(RED).width(100).height(200);


    Ced

  2. Guillaume Laforge Says:

    I love “chained methods” (that’s how I tend to call them), and that’s also why I love jMock so much: for its readability! Look at that:
    mockSubscriber.expects(once()).method(”receive”).with( same(message) );

  3. Ross Judson Says:

    I’ve been working on a JDK 5 library that lets you do something like what you’re talking about. I started with the notion that Iterable was a good thing, but Stream extends Iterable could be much better. Note that as calls are made in these examples the full type of the stream is preserved…if you create a subclass of the stream types you still get to call your subclass’s methods.

    Hopefully it’ll get to the point where I can put it out somewhere. Right now I use it to do lots of different things; SQL-like data selection, reflection over object graphs, etc…

    A couple of call examples follow.

    public void testPipeline() {
    Pipeline pipeStart = new Pipeline();

    Stream> is = pipeStart
    .shuffle()
    .first(5)
    .sort()
    .transform(new Transform(){
    public String transform(Integer from)
    {
    return “Hello ” + from;
    }})
    .end(pipeStart);

    is = is.insert(Integers.random(25));
    is.dump(”Hello “);

    System.out.println(is.getClass().getName());

    //.dump(”Hello”);

    }

    public void testAugment2() {
    randomEmployees(100)
    .where(new Transform() {
    public Boolean transform(Employee from) {
    return from.getName().startsWith(”Kurt”);
    }})
    .dump(”Employees starting with Kurt”)
    .transform(new Transform>() {
    public Tuple2 transform(Employee from) {
    return Tuple.make(from, from.hashCode());
    } })
    .dump(”Employee–hashcode tuples”);
    }

  4. Ross Judson Says:

    Let this be a lesson to you, young man. Do not attempt to put type annotations into comment examples ;)

  5. Keith Lea Says:

    I think that chained method calls are ugly, confusing, and that they pollute the simplicity of Java.

  6. Cameron Says:

    That Keith dude is right on. Your complaint is with the language, not with the return value declaration! What you really are asking for is a “with” clause. Peace.

  7. David Flanagan Says:

    java.nio has chained methods.

    In the right API, and used in moderation, they can be cool. But Keith is right that they can easily be abused and lead to ugly, confusing code.

  8. Sam Newman Says:

    Can I suggest looking at the Law of demeter? It’s been around a while: http://c2.com/cgi/wiki?LawOfDemeter

    It’s one of those OO things.

    Using “it’s in the Java API!” as justification for something has left us with a large amount of code that’s as nice to use as the calendar API. The JMock example is something else entirely – there it’s using the syntax of Java to produce readable assertions – it’s an allowable exception (in my opinion) to the law of demeter.

  9. icoloma Says:

    This is not a good thing. Get a NPE in this sentence and try to debug it.

    Java is not english, don’t try to make it so.

    mockSubscriber.expects(once()).method(”receive”).with( same(message) );

  10. Roger Desroches Says:

    Just change it to

    mockSubscriber.expects(once())
     &nbsp .method(”receive”).
     &nbsp .with( same(message) );

    The line number of the exception will reflect the line call. Also, the exception itself will reflect which method call; either expects, once() method, with, same, or the calling method.

    I use “chained calls” all the time with string buffers.

    StringBuffer buf = new StringBuffer();
    buf.append(”There have been “)
     &nbsp .append(count)
     &nbsp .append(” errors in the “)
     &nbsp .append(systemName)
     &nbsp .append(” system in the last “)
     &nbsp .append(timeDelta).append(” “)
     &nbsp .append(timeGranularity);

  11. Greg Dennis Says:

    I think chained-methods are nice and useful, but they give the impression that the object is immutable — that it has to return a new instance rather than perform a mutation. The last thing you want is for clients not to realize they are mutating an object when they are. I would recommend using chained methods if and only if the object is immutable.

    If there’s one exception, it’s StringBuffer, because (1) it’s used so frequently; (2) it so significantly reduces the amount of code; and (3) it’s very well known that it’s mutable.

  12. Helly Says:

    captive

Leave a Reply

Spam is a pain, I am sorry to have to do this to you, but can you answer the question below?

Q: Type in the word 'cricket'