73 votes

appeler les setters d'un constructeur

Quels sont les avantages et les inconvénients d'appeler un mutateur d'un constructeur (le cas échéant)

c'est à dire:

 public MyConstructor(int x) {
  this.x = x;
}
 

contre:

 public MyConstructor(int x) {
  setX(x);
}

public void setX(int x) {
  this.x = x;
}
 

Avez-vous une préférence? (Ce n'est pas des devoirs, il suffit de regarder notre document sur les normes de codage où il est dit de toujours appeler les mutateurs lors de la définition des instances var dans le constructeur et je ne le fais pas toujours)

93voto

Jon Skeet Points 692016

Personnellement, je voudrais définir la variable directement dans la plupart des cas.

Les méthodes généralement s'attendre à ce que l'instance est entièrement formée par le temps, ils sont appelés. En particulier, l'appel d'une méthode redéfinie à partir d'un constructeur est une recette pour un dur-à-la compréhension du code et difficiles à repérer les bogues.

Cela dit, j'ai souvent essayer de faire les classes immuables de toute façon, dans ce cas non seulement il n'y a pas de jour, mais vous avez à définir la finale de la variable dans le constructeur (ou une variable d'initialiseur) de toute façon :)

Où les propriétés ont la logique, le setter de la logique est généralement de validation et parfois changer de propagation pour les observateurs. J'avais l'habitude de s'attendre les paramètres du constructeur à être vérifié explicitement au début de la méthode, vous n'avez pas envie de tout changement de la propagation de se produire devant une instance est entièrement créés de toute façon.

37voto

Bert F Points 27237

J'ai suivi deux règles sur les constructeurs afin de minimiser les problèmes qui sont la raison pour laquelle je ne voudrais pas utiliser la méthode mutateur:

Les constructeurs (de classes non-finales) doit appeler uniquement finale du ou des méthodes privées. Si vous décidez d'ignorer cette règle et de laisser l'appel du constructeur de la non-final/non-méthodes privées, alors:

  • ces méthodes et les méthodes qu'ils peuvent appeler devez être prudent de ne pas assumer l'instance est complètement initialisé, et
  • les sous-classes qui remplacent ces méthodes (sous-classes qui peuvent même ne pas être conscient que le constructeur de la superclasse est des appels à ces méthodes) ne doit pas supposer que le constructeur de sous-classe et super-classes des constructeurs ont été entièrement exécutée. Ce problème s'aggrave le plus profond en bas de la hiérarchie d'héritage de la classe mère avec le "mal" constructeur est.

Est tout ce qui cognitif supplémentaire de bagages en vaut la peine? Vous pouvez autoriser une exception pour la simple mutateurs que seulement affecter une valeur à une variable d'instance, puisqu'il y a peu d'avantages, même ce qui ne semble pas en valoir la peine.

[[ @Jon Skeet mentionne dans sa réponse: "... En particulier, l'appel d'une méthode redéfinie à partir d'un constructeur est une recette pour un dur-à-la compréhension du code et difficiles à repérer les bogues." Mais je ne pense pas que les conséquences de ce problème est assez souligné. ]]

Les constructeurs devraient être prudents au sujet des fuites this avant que l'instance est complètement initialisé. Alors que la règle précédente était sur les méthodes à l'intérieur de la classe et sous-classes accéder à ivars, vous devez aussi être prudent quant à l' (même final/privé) des méthodes de passage this pour les autres classes et les fonctions de l'utilitaire avant d' this est complètement initialisé. Le plus non-privé, des méthodes substituables que le constructeur appelle, plus le risque de fuites this.


Un ouvrage de référence sur les constructeurs d'appel non définitif, non-privé méthodes:

http://benpryor.com/blog/2008/01/02/dont-call-subclass-methods-from-a-superclass-constructor/

2voto

britishmutt Points 1133

Je le fais rarement, et je n'ai jamais eu de problème à cause de cela. Cela peut également avoir des conséquences inattendues, en particulier si vos setters sont remplacés dans une sous-classe, ou si vos setters déclenchent des appels de méthode supplémentaires qui pourraient ne pas être appropriés pendant l'initialisation.

2voto

Tyler Holien Points 1645

À moins que votre setter ne fasse quelque chose de plus complexe que this.x = x , je définirais simplement la variable directement. Le paramètre correspond directement à votre variable d'instance, et pour moi, il est plus révélateur d'intention.

1voto

gbvb Points 792

Cela dépend de la façon dont vous traitez les setters. Si vous pensez que la classe peut être dérivée, vous pouvez autoriser un tel appel afin de pouvoir remplacer le comportement ailleurs. Sinon, vous pouvez le définir comme tel.

Bien sûr, Autoriser explicitement les setters fournirait également des moyens d'injecter des comportements supplémentaires pendant le paramétrage (comme appliquer la sécurité si nécessaire).

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