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).
精彩评论