43

我在许多 Java 代码符号中看到,在我们调用另一个方法之后,这里有一个示例。

Toast.makeText(text).setGravity(Gravity.TOP, 0, 0).setView(layout).show();

正如您在调用makeText返回后看到的那样,我们调用setGravity了到目前为止

我怎样才能用我自己的课程做到这一点?我需要做一些特别的事情吗?

4

6 回答 6

93

这种模式被称为“Fluent Interfaces”(参见Wikipedia

只是return this;从方法而不是什么都不返回。

所以例如

public void makeText(String text) {
    this.text = text;
}

会成为

public Toast makeText(String text) {
    this.text = text;
    return this;
}
于 2010-05-20T08:55:29.233 回答
13
class PersonMethodChaining {
    private String name;
    private int age;
 
    // In addition to having the side-effect of setting the attributes in question,
    // the setters return "this" (the current Person object) to allow for further chained method calls.
 
    public PersonMethodChaining setName(String name) {
        this.name = name;
        return this;
    }
 
    public PersonMethodChaining setAge(int age) {
        this.age = age;
        return this;
    }
 
    public void introduce() {
        System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
    }
 
    // Usage:
    public static void main(String[] args) {
        PersonMethodChaining person = new PersonMethodChaining();
        // Output: Hello, my name is Peter and I am 21 years old.
        person.setName("Peter").setAge(21).introduce();
    }
}

没有方法链

class Person {
    private String name;
    private int age;
 
    // Per normal Java style, the setters return void.
 
    public void setName(String name) {
        this.name = name;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public void introduce() {
        System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
    }
 
    // Usage:
    public static void main(String[] args) {
        Person person = new Person();
        // Not using chaining; longer than the chained version above.
        // Output: Hello, my name is Peter and I am 21 years old.
        person.setName("Peter");
        person.setAge(21);
        person.introduce();
    }
}

方法链接,也称为命名参数习语,是面向对象编程语言中调用多个方法调用的常用语法。每个方法都返回一个对象,允许在单个语句中将调用链接在一起。链接是语法糖,它消除了对中间变量的需求。方法链也被称为火车残骸,因为即使在方法之间经常添加换行符,随着更多方法链接在一起,同一行中一个接一个地出现的方法数量也会增加。

类似的语法是方法级联,在方法调用之后,表达式计算为当前对象,而不是方法的返回值。级联可以使用方法链来实现,方法是让方法返回当前对象本身(this)。级联是流畅接口中的一项关键技术,并且由于链式在面向对象语言中广泛实现,而级联不是,这种形式的“通过返回 this 进行级联”通常简称为“链式”。链接和级联都来自 Smalltalk 语言。

于 2015-01-29T18:12:33.717 回答
6

从你的例子:

Toast.makeText(text).setGravity(Gravity.TOP, 0, 0).setView(layout).show();

链中的每个方法都必须返回一个类或一个接口。链中的下一个方法必须是返回类的一部分。

我们从吐司开始。在 Toast 类中定义为静态方法的 makeText 方法必须返回一个类或一个接口。在这里,它返回 Gravity 类的一个实例。

在 Gravity 类中定义的方法 setGravity 返回 View 类的实例,

在 View 类中定义的方法 setView 返回 JPanel 类的实例。

这个链可以一步一步写出来。

Gravity gravity = Toast.makeText(text);
View view       = gravity.setGravity(Gravity.TOP, 0, 0);
JPanel panel    = view.setView(layout);
panel.show();

将链写成链会从源代码中删除所有中间实例变量。

于 2010-05-20T09:11:39.653 回答
5

在 google 上搜索 builder pattern 或 fluent interface 以获得更多详细信息。

在大多数情况下,在方法末尾返回“this”可以解决问题。

于 2010-05-20T08:56:48.560 回答
1

添加返回这个;肯定会有助于链接此类,但对于子类则失败。

如果您还希望将链接行为继承到子类,请更改您的类签名,如下所示:

类超类 < 子类扩展超类 >{}

这样所有子类都将继承方法链。

例子:

public class SuperClass<SubClass extends SuperClass> {

    public SubClass testMethod(){
        return (SubClass)this;
    }

    public static void main(String[] args) {
        SuperClass<SuperClass> superClass = new SuperClass<SuperClass>();
        superClass.testMethod().testMethod().testMethod();
        System.out.println(superClass.toString());
    }

}
于 2017-09-13T12:18:16.907 回答
-1

或者您可以使用Diezel,它会根据您的 fluent API 的正则表达式生成您需要的所有接口。

于 2011-12-13T19:49:40.037 回答