140 votes

Modèle Builder dans Effective Java

J'ai récemment commencé à lire Effective Java de Joshua Bloch. J'ai trouvé l'idée du pattern Builder [Item 2 dans le livre] vraiment intéressante. J'ai essayé de l'implémenter dans mon projet mais il y avait des erreurs de compilation. Voici en essence ce que j'essayais de faire :

La classe avec plusieurs attributs et sa classe builder :

public class NutritionalFacts {
    private int sodium;
    private int fat;
    private int carbo;

    public class Builder {
        private int sodium;
        private int fat;
        private int carbo;

        public Builder(int s) {
            this.sodium = s;
        }

        public Builder fat(int f) {
            this.fat = f;
            return this;
        }

        public Builder carbo(int c) {
            this.carbo = c;
            return this;
        }

        public NutritionalFacts build() {
            return new NutritionalFacts(this);
        }
    }

    private NutritionalFacts(Builder b) {
        this.sodium = b.sodium;
        this.fat = b.fat;
        this.carbo = b.carbo;
    }
}

Classe où j'essaie d'utiliser la classe ci-dessus :

public class Main {
    public static void main(String args[]) {
        NutritionalFacts n = 
            new NutritionalFacts.Builder(10).carbo(23).fat(1).build();
    }
}

Je reçois l'erreur de compilation suivante :

an enclosing instance that contains effectivejava.BuilderPattern.NutritionalFacts.Builder is required NutritionalFacts n = new NutritionalFacts.Builder(10).carbo(23).fat(1).build();

Je ne comprends pas ce que le message signifie. Veuillez expliquer. Le code ci-dessus est similaire à l'exemple suggéré par Bloch dans son livre.

1 votes

178voto

Bozho Points 273663

Rendez le constructeur une classe static. Ensuite, cela fonctionnera. S'il n'est pas statique, il nécessiterait une instance de sa classe propriétaire - et le but n'est pas d'avoir une instance de celui-ci, et même d'interdire de faire des instances sans le constructeur.

public class NutritionFacts {
    public static class Builder {
    }
}

Référence : Classes imbriquées

34 votes

Et, en fait, Builder est static dans l'exemple du livre (page 14, ligne 10 dans la 2ème édition).

14voto

analytically Points 45

Pour générer un générateur interne dans Intellij IDEA, consultez ce plugin : https://github.com/analytically/innerbuilder

2 votes

Cela n'a rien à voir avec la question posée mais c'est très utile! Belle trouvaille!

12voto

Michael K Points 947

Vous essayez d'accéder à une classe non statique de manière statique. Changez Builder en static class Builder et cela devrait fonctionner.

L'exemple d'utilisation que vous donnez échoue car il n'y a aucune instance de Builder présente. Une classe statique est toujours instanciée pour tous les besoins pratiques. Si vous ne la déclarez pas statique, vous devriez dire :

Widget = new Widget.Builder(10).setparm1(1).setparm2(3).build();

Parce que vous auriez besoin de construire un nouveau Builder à chaque fois.

8voto

Grzegorz Oledzki Points 10491

Vous devez déclarer la classe interne Builder comme static.

Consultez la documentation pour les classes internes non statiques et les classes internes statiques.

Fondamentalement, les instances des classes internes non statiques ne peuvent pas exister sans une instance de classe extérieure attachée.

3voto

Shaun Points 1842

La classe Builder devrait être statique. Je n'ai pas le temps en ce moment de tester réellement le code au-delà de ça, mais si cela ne fonctionne pas, faites-le moi savoir et je jetterai un autre coup d'œil.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X