开发者

Creating java methods that can be called like this: foo.bar().baz().quux()

I'm not sure what it's called exactly, but I was wondering how you can create a class whic开发者_如何转开发h 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?


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


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


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.


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


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.


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.


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();


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).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜