简体   繁体   English

创建可以像这样调用的java方法:foo.bar()。baz()。quux()

[英]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 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: 例如,使用android类但它并不重要,您可以立即调用所有类的方法:


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. 我认为这可行的唯一方法是,如果每个方法都返回了this ,但这似乎会导致问题。 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 . 你只需要函数返回this而不是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: 另外,不是建立你的类总是返回“this”,你也可以使用double brace类实例化hack,使用普通的java类:

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

here's a good reference -- http://www.c2.com/cgi/wiki?DoubleBraceInitialization 这是一个很好的参考 - http://www.c2.com/cgi/wiki?DoubleBraceInitialization

That's the Builder Pattern . 那是Builder模式
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. 返回this是实现这一目标的标准做法。

Java StringBuilder is an example. Java StringBuilder就是一个例子。 ( see source ) 见来源

It is said that such classes have a fluent interface 据说这些类具有流畅的界面

The idea behind this is returning a reference to this . 这背后的想法是返回到参考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 . 您将在使用Builder Pattern的类(如AlertDialog.Builder看到此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. 请注意,好的设计往往会在末尾调用.build()来返回正在构建的实例。

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. 如果构建器对象是可变的并且方法调用正在修改某个内部构建器状态,那么这可以是“this”。 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. 一个(虽然很差)解决方案是使用一个Boolean参数重载所有方法,返回ReturnThis,调用该函数,然后返回它。 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!) (ZOMG这是一个糟糕的解决方案!)

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!) 使用C#并创建一个方法,该方法接受一个委托参数数组(函数指针),并循环遍历数组并调用它们(更糟糕的是!)

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). 或者使用上述三个选项之一(但如果您正在执行此步骤,则会对您的要求的有效性产生疑问)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 新的Foo(bar)是什么{public void baz(){…}}; 在Java中意味着什么? - What does new Foo(bar) {public void baz(){…} }; mean in Java? “$ {foo.bar}”和“#{foo.bar}”之间的区别是什么? - Whats the difference between “${foo.bar}” and “#{foo.bar}”? 我可以告诉javac忽略`import foo.Bar`的缺失吗? - Can I tell javac to ignore the lack of `import foo.Bar`? Kotlin语法混乱:好玩Foo.bar()=(...) - Kotlin syntax confusion: fun Foo.bar() = (…) 我正在使用 JAVA Spring Boot REST API 和 Hibernate/JPA 问题是表名,当我需要访问的名称在名称中包含一个点,如 FOO.BAR - I am using JAVA Spring Boot REST API and Hibernate/JPA issue is with table name when the name I need to access contains a dot in the name like FOO.BAR 这段代码我错过了什么? 谷歌foo.bar - What am I missing with this code? Google foo.bar Google Foo.Bar Challenge Help Minion Salutes - Google Foo.Bar Challenge Help Minion Salutes 如何测试接口Foo <Bar> 来自巴兹的“可转让”? - How to test if interface Foo<Bar> is “assignable” from Baz? 这将在哪些测试用例上失败? Google foo.bar挑战bomb_baby - What test cases would this fail on? Google foo.bar Challenge bomb_baby 错误:“包在模块‘foo.bar’中声明为‘javafx.beans.value’” - Error: "Package is declared 'javafx.beans.value' in module 'foo.bar'"
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM