J'ai récemment commencé à lire Effective Java de Joshua Bloch. J'ai trouvé l'idée du modèle Builder [Item 2 dans le livre] vraiment intéressante. J'ai essayé de l'implémenter dans mon projet mais il y a eu des erreurs de compilation. Voici ce que j'essayais de faire:
La classe avec plusieurs attributs et sa classe de générateur:
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'essaye 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();
}
}
J'obtiens l'erreur de compilateur suivante:
une instance englobante qui contient effectivejava.BuilderPattern.NutritionalFacts.Builder est requise NutritionalFacts n = new NutritionalFacts.Builder (10) .carbo (23) .fat (1) .build ();
Je ne comprends pas ce que signifie le message. S'il vous plaît, expliquez. Le code ci-dessus est similaire à l'exemple suggéré par Bloch dans son livre.
la source
Réponses:
Faites du constructeur une
static
classe. Ensuite, cela fonctionnera. S'il n'est pas statique, il nécessiterait une instance de sa classe propriétaire - et le but est de ne pas en avoir d'instance, et même d'interdire la création d'instances sans le générateur.Référence: classes imbriquées
la source
Builder
eststatic
dans l'exemple du livre (page 14, ligne 10 dans la 2e édition).Vous devez rendre la classe Builder statique et vous devez également rendre les champs finaux et avoir des getters pour obtenir ces valeurs. Ne fournissez pas de setters à ces valeurs. De cette façon, votre classe sera parfaitement immuable.
Et maintenant, vous pouvez définir les propriétés comme suit:
la source
final
Les champs n'ont de sens que si les champs sont toujours nécessaires lors de l'initialisation. Sinon, les champs ne devraient pas l'êtrefinal
.Vous essayez d'accéder à une classe non statique de manière statique. Changez
Builder
pourstatic class Builder
et cela devrait fonctionner.L'exemple d'utilisation que vous donnez échoue car il n'y a aucune instance de
Builder
present. Une classe statique à toutes fins pratiques est toujours instanciée. Si vous ne le rendez pas statique, vous devrez dire:Parce que vous auriez besoin d'en construire un nouveau à
Builder
chaque fois.la source
Pour générer un constructeur interne dans Intellij IDEA, consultez ce plugin: https://github.com/analytically/innerbuilder
la source
Vous devez déclarer la
Builder
classe interne commestatic
.Consultez de la documentation pour les classes internes non statiques et les classes internes statiques .
Fondamentalement, les instances de classes internes non statiques ne peuvent pas exister sans instance de classe externe attachée.
la source
Une fois que vous avez une idée, dans la pratique, vous trouverez peut-être le lombok
@Builder
beaucoup plus pratique.@Builder
vous permet de produire automatiquement le code requis pour que votre classe soit instanciable avec du code tel que:Documentation officielle: https://www.projectlombok.org/features/Builder
la source
Cela signifie que vous ne pouvez pas créer de type fermé. Cela signifie que vous devez d'abord créer une instance de classe "parent", puis à partir de cette instance, vous pouvez créer des instances de classe imbriquées.
Classes imbriquées
la source
La classe Builder doit être statique. Je n'ai pas le temps pour le moment de tester le code au-delà de cela, mais si cela ne fonctionne pas, faites-le moi savoir et je vais jeter un autre coup d'œil.
la source
Personnellement, je préfère utiliser l'autre approche, lorsque vous avez 2 classes différentes. Vous n'avez donc besoin d'aucune classe statique. C'est essentiellement pour éviter d'écrire
Class.Builder
lorsque vous devez créer une nouvelle instance.Ainsi, vous pouvez utiliser votre constructeur comme ceci:
la source
Comme beaucoup l'ont déjà dit ici, vous devez faire le cours
static
. Juste un petit ajout - si vous voulez, il y a une manière un peu différente sans statique.Considère ceci. Implémenter un générateur en déclarant quelque chose comme des
withProperty(value)
types setters à l'intérieur de la classe et en leur faisant renvoyer une référence à lui-même. Dans cette approche, vous avez une classe unique et élégante qui est un thread sûr et concis.Considère ceci:
Consultez-le pour plus d' exemples Java Builder .
la source
Vous devez changer la classe Builder en classe statique Builder . Ensuite, cela fonctionnera très bien.
la source