Question

Je venais de lire une la présentation de Java 7 (pdf) . une diapositive sur Invocation chaînée . Voici l'exemple utilisé dans la diapositive:

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

Et j'ai des sentiments mitigés à ce sujet. Il ne faut pas enchaîner trop d'appels de méthodes dans une seule instruction. D'autre part, écrire margarita.this () et margarita.that () n'est pas très pratique non plus.

Maintenant, je viens à Java du monde Delphi. Et dans Delphi, il existe le avec langage construit. Ceci est chéri par quelques-uns et détesté par beaucoup (ou est-ce l'inverse?). Je trouve que avec est plus élégant que l’idée d’une invocation en chaîne (qui, je crois, fonctionne sur la base de la méthode void renvoyant une référence à un objet sur lequel elle a été invoquée - et C'est la partie que je n'aime pas, car void devrait renvoyer rien ).

J'apprécierais que Java adopte la fonctionnalité de langage avec , afin que l'exemple de code puisse être écrit comme suit:

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

Suis-je le seul à préférer cette solution à l’invocation chaînée? Quelqu'un d'autre pense que avec pourrait être une extension utile du langage Java? (Cela me rappelle la question de quelqu'un sur la nécessité de "Java ++" ...)

Était-ce utile?

La solution

l'instruction avec peut être traduite en Java à l'aide de classes anonymes avec initializer:

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

les inconvénients de l'utilisation de cet idiome sont bien documentés ici .

L'invocation chaînée est un alias pour le chaînage de méthodes. C’est un idiome bien connu qui fonctionne avec n’importe quelle version de Java:

class Chained {

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

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

Une proposition pour JDK 7 consiste à autoriser la méthode de chaînage également pour le type de retour nul :

class ChainedJava7 {

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

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

Autres conseils

Cela pourrait vous intéresser.

J'aime assez avec les déclarations de cette forme, mais je préfère leur version VB:

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

Comme chaque attribut du bloc With doit toujours être précédé d'un . , vous savez que vous référencez une propriété Object et non, par exemple, une variable locale. , en réduisant les collisions entre espaces de noms.

Si nous prenons votre exemple:

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

il n’existe aucun moyen simple de savoir si withSalt () est une méthode de DrinkBuilder ou une méthode de la classe locale. Si vous n'autorisez que les méthodes de à objet dans le bloc à , je pense qu'elles deviennent beaucoup moins utiles.

Je ne suis pas fan de cette utilisation de avec ; Je préfère de loin l'instruction Python avec . Je conviens avec vous que void devrait signifier void . Dans l'exemple que vous donnez, si une personne veut vraiment pouvoir chaîner les invocations de méthode, elle doit simplement changer les types de retour sur ses méthodes afin qu'elles puissent être chaînées.

Peut-être que les nombreux appels vers un même objet sont le signe que du code doit être déplacé?

Joshua Bloch dans Java efficace , le n ° 2 recommande vivement l'utilisation d'un Builder quand vous avez un constructeur avec beaucoup d'arguments. Une des raisons est qu'il peut être écrit pour garantir que l'objet construit est toujours dans un état cohérent. Cela évite également d'avoir des "constructeurs télescopiques" complexes. dans la classe de l'objet construit. Encore une autre possibilité est que si vous voulez que l’objet construit soit immuable (par exemple, pour la sécurité des threads), il ne peut pas avoir de méthode de définition.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top