Как сделать цепочку методов в Java? o.m1 (). м2 (). м3 (). m4 () - PullRequest
35 голосов
/ 20 мая 2010

Я видел во многих нотациях кода Java, что после метода, который мы вызываем другой, вот пример.

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

Как вы видите после звонка makeText на возврат, мы звоним setGravity и до сих пор

Как я могу сделать это с моими собственными классами? Должен ли я сделать что-то особенное?

Ответы [ 6 ]

86 голосов
/ 20 мая 2010

Этот шаблон называется «Свободные интерфейсы» (см. Википедия )

Просто return this; из методов вместо того, чтобы ничего не возвращать.

Так например

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

станет

public Toast makeText(String text) {
    this.text = text;
    return this;
}
10 голосов
/ 29 января 2015
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). Каскадирование является ключевым методом в свободно распространяемых интерфейсах, и поскольку цепочка широко реализована в объектно-ориентированных языках, а каскадирование - нет, эту форму «каскадирования по цепочке путем возврата этого» часто называют просто «цепочкой». И цепочка, и каскадирование происходят от языка Smalltalk.

4 голосов
/ 20 мая 2010

Из вашего примера:

Toast.makeText (текст) .setGravity (Gravity.TOP, 0,0)

Каждый метод в цепочке должен возвращать класс или интерфейс. Следующий метод в цепочке должен быть частью возвращаемого класса.

Начнем с тоста. Метод makeText, который определен как статический метод в классе Toast, должен возвращать класс или интерфейс. Здесь он возвращает экземпляр класса Gravity.

Метод setGravity, определенный в классе Gravity, возвращает экземпляр класса View,

Метод setView, определенный в классе View, возвращает экземпляр класса JPanel.

Эта цепочка может быть записана шаг за шагом.

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

Запись цепочки в виде цепочки удаляет все переменные промежуточного экземпляра из исходного кода.

3 голосов
/ 20 мая 2010

Найдите шаблон для построения или свободный интерфейс в Google, чтобы получить более подробную информацию об этом.

Возврат 'this' в конце вашего метода может помочь в большинстве случаев.

1 голос
/ 13 сентября 2017

Добавление вернуть это; несомненно, поможет в цепочке для этого класса, но не для подклассов.

Если вы хотите, чтобы поведение связывания наследовалось подклассам, также измените сигнатуру вашего класса, как показано ниже:

Класс SuperClass {}

Таким образом, все подклассы будут наследовать цепочку методов.

Пример:

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

}
0 голосов
/ 13 декабря 2011

или вы можете использовать Diezel , который генерирует все необходимые интерфейсы на основе регулярного выражения вашего свободного API.

...