views:

126

answers:

8

I'm not sure what it's called exactly, but I was wondering how you can create a class which you can call multiple methods on in one call. For example, using an android class but it doesn't really matter, you can call all of the class' methods at once:


AlertDialog.Builder().setItem().setTitle().setPositiveButton().setCancelable() ...etc

The only way I can think that this could work is if every method returned this, but that seems like it would cause problems. I'm not sure how, but it just seems like it would.

Also, does this technique have a name?

+7  A: 

This technique is called method chaining, and it works exactly as you've imagined. You simply have functions return this instead of void.

VeeArr
You were first and answered in the least number of characters =]
Falmarri
+1  A: 

It won't cause problems. Returning this is the standard practice to achieve this.

Java StringBuilder is an example. (see source)

It is said that such classes have a fluent interface

Bozho
+1  A: 

The idea behind this is returning a reference to this. Let's look at a simple example:

class A{
    public A setStuffs(){
        return this;
    }
    public A setOtherStuffs(){
        return this;
    }
}

Then you can do:

A a = new A().setStuffs().setOtherStuffs();

You will see this in classes that use the Builder Pattern like AlertDialog.Builder. But, I usually do it in every class I do, because it help me save lines of code.

Cristian
+1  A: 

That's the Builder Pattern.
What you are effectively doing is:

AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setIcon(android.R.drawable.icon);
builder.setTitle(R.string.title);
builder.setMessage(R.string.message);
//etc.
alex
A: 

This is called method chaining and the easiest way to gain that effect is to return the current instance of the object from each method...

class MyCoolChainingObject{

    public MyCoolChainingObject doSomething(){
        //TODO: Stuff
        return this;
    }

    public MyCoolChainingObject doSomethingElse(){
        //TODO: Stuff
        return this;
    }  
}

....

new MyCoolChainingObject().doSomething().doSomethingElse();
Quintin Robinson
A: 

I've always called this kind of object a "builder".

Note that the good designs tend have a .build() call at the end to return the instance that you are building.

As you suggest, all of the intermediate method calls return a builder object. This can be "this" if the builder object is mutable and the methods calls are modifying some internal builder state. Alternatively, if the builder object is immutable, the calls could each return a completely new immutable builder object.

mikera
p.s. if you are designing an API like this, I'd recommend making the builder objects immutable.... it can save significant pain in the long run when users start passing builder objects around and using them in different threads. This is pretty easy to do by storing the backing data in some for of persistent data structure.
mikera
A: 

Every person who described method chaining exemplified a perfectly reasonable way to achieve this, but only whenever your functions don't need to return something. What if you wanted to return something?

A (albeit poor) solution is to overload all your methods with a boolean argument for ReturnThis, which calls the function, then returns this. However, I'd definitely recommend the builder pattern in lieu of this.

OR! A function that takes a bitwise argument selecting which functions you wish to execute! (ZOMG that's an awful solution!)

OR STILL! Use C# and create a method which takes a parameter array of delegates (function pointers), and loop over the array and call them all (Even worse still!)

These are the only options I could come up with. If you can't do method chaining, go for builder, or just call them all on their own line. Or use one of the three options above (but really call into question the validity of your requirements if you're on this step).

Ziplin
+2  A: 

also, rather than building your class to always return "this", you could also just use the double brace class instantiation hack, with a normal java class:

AlertDialog.Builder(){{
  setItem();
  setTitle();
  setPositiveButton();
  setCancelable();
   ...etc
}}

here's a good reference -- http://www.c2.com/cgi/wiki?DoubleBraceInitialization

chrismarx
And a `.create()` at the end: `AlertDialog dialog = AlertDialog.Builder() {{ ... }}.create();`
Tom Hawtin - tackline
I use the double brace instantiation hack all the time for test code. For production code, I avoid it... because it winds up creating a new class for each time you do it (you're subclassing). This is a cost I prefer to avoid.
RHSeeger