Pregunta

Estaba leyendo una presentación preliminar de Java 7 (pdf) y había una diapositiva sobre Invocación encadenada . Aquí está el ejemplo utilizado en la diapositiva:

// Construction with setters
DrinkBuilder margarita = new DrinkBuilder();
margarita.add("tequila");
margarita.add("orange liqueur");
margarita.add("lime juice");
margarita.withRocks();
margarita.withSalt();
Drink drink = margarita.drink();

// Construction with chained invocation
Drink margarita = new DrinkBuilder()
    .add("tequila")
    .add("orange liqueur")
    .add("lime juice")
    .withRocks()
    .withSalt()
    .drink();

Y tengo sentimientos encontrados sobre esto. No se deben encadenar demasiadas invocaciones de métodos en una sola declaración. Por otro lado, escribir margarita.this () y margarita.that () tampoco es demasiado conveniente.

Ahora, estoy llegando a Java desde el mundo de Delphi. Y en Delphi está el con construcción del lenguaje. Algunos lo aprecian y muchos lo detestan (¿o es al revés?). Creo que with es más elegante que la idea de invocación encadenada (que creo que funciona sobre la base del método void que devuelve la referencia al objeto en el que se ha invocado, y esta es la parte que no me gusta, ya que void debería devolver nothing ).

Agradecería que Java adoptara la función de lenguaje with , por lo que el código de ejemplo podría escribirse así:

Drink margarita = null;
with (new DrinkBuilder()) {
    add("tequila");
    add("orange liqueur");
    add("lime juice");
    withRocks();
    withSalt();
    margarita = drink();
}

¿Soy el único que preferiría esta solución a la invocación encadenada? ¿Alguien más siente que with podría ser una extensión útil para el lenguaje Java? (Me recuerda a la pregunta de alguien sobre la necesidad de "Java ++" ...)

¿Fue útil?

Solución

la declaración con se puede traducir en Java utilizando clases anónimas con inicializador:

Drink margarita = new DrinkBuilder() {{
    add(“tequila”);
    add(“orange liqueur”);
    add(“lime juice”);
    withRocks();
    withSalt();
}}.drink();

las desventajas de usar este idioma están bien documentadas aquí .

La invocación encadenada es un alias para el método de encadenamiento. Ese es un idioma muy conocido y funciona con cualquier versión de Java:

class Chained {

    public Chained withFoo() { 
        // ...
        return this;
    }

    public Chained withBar() { 
        // ...
        return this;
    }
}    

una propuesta para JDK 7 es permitiendo el método de encadenamiento también para el tipo de retorno nulo :

class ChainedJava7 {

    public void withFoo() { 
        // ...
    }

    public void withBar() { 
        // ...
    }
}    

Otros consejos

Esto podría interesarle.

Me gustan bastante las declaraciones de with de esa forma, pero prefiero la versión VB de ellas:

With testObject
    .Height = 100
    .Text = "Hello, World"
    .ForeColor = System.Drawing.Color.Green
End With

Como cada atributo en el bloque With todavía tiene que estar precedido por un . sabes que estás haciendo referencia a una propiedad Object y no, por ejemplo, a una variable local , reduciendo cualquier colisión de espacio de nombres.

Si tomamos su ejemplo:

with (new DrinkBuilder()) {
    add(“tequila”);
    add(“orange liqueur”);
    add(“lime juice”);
    withRocks();
    withSalt();
    margarita = drink();
}

no hay una manera fácil de saber si withSalt () es un método de DrinkBuilder o un método en clase local. Si solo permite métodos del objeto with ed en el bloque with , creo que se vuelven mucho menos útiles.

No soy fanático de este uso de con ; Prefiero la Python con declaración . Sin embargo, estoy de acuerdo con usted en que void debería significar void . En el ejemplo que proporciona, si una persona realmente quiere poder encadenar invocaciones de métodos, simplemente debe cambiar los tipos de retorno en sus métodos para que sean encadenables.

¿Quizás las muchas llamadas a un objeto son la señal de que se debe mover algún código?

Joshua Bloch en Java efectivo El ítem # 2 recomienda encarecidamente el uso de un Constructor cuando tienes un constructor con muchos argumentos. Una razón es que se puede escribir para garantizar que el objeto construido siempre esté en un estado coherente. También evita tener constructores telescópicos complejos. en la clase del objeto construido. Otra más es que si desea que el objeto construido sea inmutable (por ejemplo, para la seguridad de subprocesos), no puede tener métodos de establecimiento.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top