Là où je travaille, je vois beaucoup de classes qui font des choses comme celle-ci:
public class ClassThatCallsItsOwnGettersAndSetters {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public void methodWithLogic() {
setField("value");
//do stuff
String localField = getField();
//do stuff with "localField"
}
}
Si j'avais écrit ça à partir de rien, j'aurais methodWithLogic()
plutôt écrit ceci:
public class ClassThatUsesItsOwnFields {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public void methodWithLogic() {
field = "value";
//do stuff
//do stuff with "field"
}
}
Je pense que lorsque la classe appelle ses propres accesseurs et régleurs, cela rend le code plus difficile à lire. Pour moi, cela implique presque que de la logique complexe se produit dans cet appel de méthode, même si dans notre cas ce n’est presque jamais. Lorsque je débogue des codes inconnus, qui peut dire que le bogue n’est pas un effet secondaire de cette méthode? En d'autres termes, cela me fait faire beaucoup de détournements pour comprendre le code.
Y a-t-il des avantages à la première méthode? La première méthode est-elle réellement meilleure?
java
object-oriented
programming-practices
Daniel Kaplan
la source
la source
Réponses:
Je ne dirai pas ce qui est meilleur ou pire, car cela dépend en partie de votre situation (à mon avis). Mais considérez que vos getters et setters peuvent changer d'implémentation plus tard, et les contourner éviterait cette logique.
Par exemple, que se passe-t-il si vous ajoutez un indicateur "sale" à certains champs de définition ultérieurement? En appelant vos traceurs dans votre code interne, vous définissez le drapeau sale sans changer aucun autre code. Dans de nombreuses situations, ce serait une bonne chose.
la source
setField()
depuis le début, vous venez d'introduire un bogue.Appeler directement le passeur n’est pas un problème en soi. La question devrait vraiment être: pourquoi notre code a-t-il des setters partout?
Les classes mutables sont un jeu dangereux, en particulier lorsque la classe gère elle-même son propre état. Considérez combien de ces setters ont vraiment besoin d'exister. Combien pourraient être définies dans le constructeur et ensuite être entièrement encapsulées par la classe elle-même?
Si le champ doit pouvoir être réglé de manière externe, demandez-vous si la méthode avec la logique devrait être là. Votre classe elle-même est-elle vraiment juste une classe de données / état? Cette classe a-t-elle plus d'une responsabilité?
Ne vous méprenez pas, il y aura des cas où tout va bien. Je ne dis pas que vous devriez éliminer complètement les setters des classes avec logique. Mais ceux-ci devraient être l'exception, pas la règle. Et, dans ces quelques cas, il devrait être évident de savoir à qui accéder directement.
la source
Oui, les méthodes de votre classe devraient appeler les getters et les setters. L’essentiel dans l’écriture des getters et des setters est la pérennité. Vous pouvez transformer chaque propriété en champ et exposer directement les données aux utilisateurs de la classe. La raison pour laquelle vous créez les getters et les setters n’est pas nécessairement due à une logique complexe, mais à ce que l’interface ne se casse pas à l’avenir si vous devez l’ajouter.
la source
someField=newValue; refresh();
Si la méthode permet de définir plusieurs champs, appeler des paramètres pour écrire ces champs entraînerait des opérations "d'actualisation" redondantes. Écrire tous les champs puis appelerrefresh()
une fois peut permettre une opération plus efficace et plus fluide.Pour répondre à vos questions en un mot, oui.
Le fait d’avoir une classe appelle ses propres getters et setters ajoute de l’extensibilité et fournit une meilleure base pour le code futur.
Disons que vous avez quelque chose comme ça:
Appeler les setters pour l'année et la marque actuellement n'ajoute probablement aucune fonctionnalité, mais que se passe-t-il si vous voulez ajouter quelque chose comme une validation d'entrée aux setters?
la source
Une chose qui n’a pas été mentionnée est que le getter et les setters (comme toutes les méthodes) sont virtuels en Java. Cela ajoute une autre fonctionnalité pour toujours les utiliser dans votre code. Un autre utilisateur pourrait étendre votre classe en écrasant vos getters et setters. Votre classe de base utiliserait alors les données de la sous-classe plutôt que les siennes. Dans un langage où vous marquez explicitement les fonctions virtuelles, ceci est beaucoup plus pratique car vous pouvez prédire et déclarer les fonctions avec lesquelles cela peut être fait. En Java, il faut toujours en être conscient. Si c'est le comportement souhaité, alors les utiliser dans votre code est une bonne chose, sinon moins.
la source
Si vous essayez d'accomplir quelque chose qui est fourni par l'interface publique, utilisez les accesseurs / régleurs.
Cependant, en tant que propriétaire / développeur de la classe, vous êtes autorisé à accéder aux sections privées de votre code (à partir de la classe, bien sûr), mais vous êtes également responsable d'atténuer les dangers.
Donc, vous avez peut-être un getter qui parcourt une liste interne et vous voulez obtenir la valeur actuelle sans incrémenter l'itérateur. Dans ce cas, utilisez la variable privée.
la source
Oui. Les accesseurs et les préposés représentent l'état, alors changez la question. Souhaitez-vous suivre de nombreuses façons de modifier l'état d'un objet de la même manière, à moins que vous n'ayez à le faire?
Moins vous avez de tâches à suivre, mieux c’est la raison pour laquelle les objets immuables sont plus faciles à gérer.
Considérez que rien ne vous empêche d’avoir à la fois un public et un passeur / passeur public - mais que gagneriez-vous?
Il peut arriver qu’il soit souhaitable, voire nécessaire, d’accéder directement au terrain pour une ou plusieurs raisons, vous ne devriez pas hésiter à le faire si cela se produit. Mais vous ne devriez vraiment le faire que s'il existe un avantage défini à le faire.
la source
Les deux méthodes ont leurs cas d'utilisation. Comme le setter public maintient la valeur du champ (et / ou les valeurs liées) cohérente, vous devez utiliser setter lorsque la logique de votre méthode n'interfère pas avec cette logique de cohérence. Si vous venez de définir votre "propriété", utilisez setter. D’autre part, il existe des situations où vous avez besoin d’un accès direct à certains champs, par exemple des opérations en bloc avec un setter lourd ou des opérations dans lesquelles le concept de setter est trop simple.
C'est votre responsabilité de garder les choses cohérentes. Setter le fait par définition, mais ne peut pas couvrir des cas complexes.
la source
Je dirais non ..
Si vos getters / setters récupèrent et définissent (pas d'initialisation lazy, pas de contrôles, etc.), utilisez simplement vos variables. Si, à l'avenir, vous modifiez vos accesseurs / configurateurs, vous pouvez très bien changer votre
methodWithLogic()
(car c'est votre classe en train de changer) et vous pouvez appeler un acquéreur / configurateur au lieu d'une affectation directe. Vous pouvez documenter cet appel pour le getter / setter (car il sera étrange d'appeler un getter / setter lorsque le reste du code de votre classe utilise directement la variable).La machine virtuelle Java appellera fréquemment les getters / setters en ligne. Donc, ce n'est jamais un problème de performance. Le gain de l’utilisation des variables est la lisibilité et à mon humble avis, j’y retournerais.
J'espère que cela t'aides..
la source