创建可以像这样调用的java方法:foo.bar().baz().quux()
我不确定它的确切名称是什么,但我想知道如何创建一个可以在一次调用中调用多个方法的类。例如,使用 android 类,但这并不重要,您可以一次调用所有类的方法:
AlertDialog.Builder().setItem().setTitle().setPositiveButton().setCancelable() ...etc
我认为这可行的唯一方法是每个方法都返回 this
,但这似乎会引起问题。我不知道如何,但看起来就是这样。
另外,这个技术有名字吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这种技术称为方法链接,它的工作原理与您想象的完全一样。您只需让函数返回
this
而不是void
即可。This technique is called method chaining, and it works exactly as you've imagined. You simply have functions return
this
instead ofvoid
.另外,您也可以使用双括号类实例化技巧和普通的 java 类,而不是构建始终返回“this”的类:
这是一个很好的参考 - http://www.c2.com/cgi/wiki?DoubleBraceInitialization
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:
here's a good reference -- http://www.c2.com/cgi/wiki?DoubleBraceInitialization
这就是构建器模式。
你正在有效地做的是:
That's the Builder Pattern.
What you are effectively doing is:
它不会造成问题。返回
this
是实现此目的的标准做法。Java
StringBuilder
就是一个例子。 (查看源码)据说这样的类有一个流畅的界面
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
这背后的想法是返回对
this
的引用。让我们看一个简单的示例:然后您可以这样做:
您将在使用 Builder 模式(如
AlertDialog.Builder
)的类中看到这一点。但是,我通常在每堂课上都会这样做,因为它可以帮助我节省代码行。The idea behind this is returning a reference to
this
. Let's look at a simple example:Then you can do:
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.我一直将这种对象称为“构建器”。
请注意,好的设计往往在最后有一个 .build() 调用来返回您正在构建的实例。
正如您所建议的,所有中间方法调用都会返回一个构建器对象。如果构建器对象是可变的并且方法调用正在修改某些内部构建器状态,则这可以是“this”。或者,如果构建器对象是不可变的,则每个调用都可以返回一个全新的不可变构建器对象。
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...
....
每个描述方法链的人都举例说明了实现此目的的完全合理的方法,但前提是您的函数不需要返回某些内容。如果您想退货怎么办?
一个(尽管很糟糕)的解决方案是使用 ReturnThis 的布尔参数来重载所有方法,它调用该函数,然后返回 this。但是,我肯定会推荐构建器模式来代替它。
或者!一个函数,它接受按位参数来选择您想要执行的函数! (ZOMG,这是一个糟糕的解决方案!)
或者仍然!使用 C# 并创建一个方法,该方法采用委托参数数组(函数指针),然后循环遍历该数组并调用它们(更糟糕的是!)
这些是我能想到的唯一选项。如果您无法进行方法链接,请使用构建器,或者只是在自己的线路上调用它们。或者使用上述三个选项之一(但如果您执行此步骤,则确实会质疑您的要求的有效性)。
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).