Cómo hacer encadenamiento de métodos en Java? o. m1 ().m2 ().m3 ().m4()


He visto en muchas notación de código Java que después de un método llamamos a otro, aquí hay un ejemplo.

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

Como ves después de llamar makeText en el retorno llamamos setGravity y hasta ahora

¿Cómo puedo hacer esto con mis propias clases? ¿Tengo que hacer algo especial?

Author: Pentium10, 2010-05-20

6 answers

Este patrón se llama "Interfaces fluidas" (ver Wikipedia)

Solo return this; de los métodos en lugar de devolver nada.

Así que por ejemplo

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

Se convertiría en

public Toast makeText(String text) {
    this.text = text;
    return this;
}
 82
Author: Thomas Lötzer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-20 09:01:21
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();
}

}

Sin método de encadenamiento

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

El encadenamiento de métodos, también conocido como named parameter idiom, es una sintaxis común para invocar múltiples llamadas a métodos en lenguajes de programación orientados a objetos. Cada método devuelve un objeto, lo que permite encadenar las llamadas en una sola instrucción. El encadenamiento es azúcar sintáctico que elimina la necesidad de variables intermedias. Una cadena de método también se conoce como un accidente de tren debido al aumento en el número de métodos que vienen uno tras otro en la misma línea que ocurre a medida que más métodos están encadenados, aunque los saltos de línea a menudo se agregan entre métodos.

Una sintaxis similar es method cascading, donde después de la llamada al método, la expresión evalúa el objeto actual, no el valor devuelto del método. La cascada se puede implementar usando el encadenamiento del método haciendo que el método devuelva el objeto actual (esto). En cascada es una técnica clave en fluent interfaces, y dado que el encadenamiento está ampliamente implementado en lenguajes orientados a objetos mientras que el encadenamiento no lo está, esta forma de "encadenamiento en cascada devolviendo esto" a menudo se conoce simplemente como "encadenamiento". Tanto el encadenamiento como la cascada provienen del lenguaje Smalltalk.

 10
Author: subhashis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-30 06:49:51

De tu ejemplo:

Brindis.makeText(texto).setGravity(Gravedad.TOP, 0, 0).setView(diseño).show ();

Cada método en la cadena tiene que devolver una clase o una interfaz. El siguiente método en la cadena tiene que ser parte de la clase devuelta.

Empezamos con Tostadas. El método makeText, que se define como un método estático en la clase Toast, tiene que devolver una clase o una interfaz. Aquí, devuelve una instancia de la clase Gravity.

El método setGravity, que se define en la clase Gravity, devuelve una instancia de la Vista de clase,

El método setView, que se define en la vista de clase, devuelve una instancia de la clase JPanel.

Esta cadena podría escribirse paso a paso.

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

Escribir la cadena como una cadena elimina todas las variables de instancia intermedias del código fuente.

 4
Author: Gilbert Le Blanc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-27 15:44:17

Busque builder pattern o fluent interface en Google para tener más detalles sobre esto.

Devolver 'esto' al final de su método puede hacer el truco en la mayoría de los casos.

 3
Author: Guillaume,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-20 08:56:48

Agregar return this; seguramente ayudaría en el encadenamiento para esta clase, pero fallaría para las subclases.

Si desea que el comportamiento de encadenamiento heredado a las subclases también cambie su firma de clase como se muestra a continuación:

Class SuperClass {}

De esta manera todas las subclases heredarán el encadenamiento del método.

Ejemplo:

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

}
 1
Author: Purushotham Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-13 12:47:29

O puede usar Diezel que genera todas las interfaces que necesita basadas en una expresión Regular de su API fluent.

 -1
Author: eric,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-13 19:49:40