web-dev-qa-db-fra.com

Pourquoi les méthodes getter et setter sont-elles importantes en java?

On m'a appris à toujours utiliser des getters et des setters. Cependant, je ne connais pas les avantages et les inconvénients de ces méthodes, car en les mettant en œuvre, nous exposons les données et les cachons également.

Je suis un peu confus à ce sujet. Quelqu'un peut-il donner des conseils appropriés sur la raison pour laquelle nous utilisons un getter/setter et quels sont les avantages?

35
School Boy

Le modèle de base "champ privé avec getter et setter public qui ne font que retourner ou définir le champ" est en effet complètement inutile en ce qui concerne l'encapsulation, sauf qu'il vous donne une chance de le changer plus tard sans changer l'API.

N'utilisez donc pas ce modèle sans réfléchir. Réfléchissez soigneusement aux opérations dont vous avez réellement besoin.

Le véritable intérêt des getters et setters est que vous ne devez les utiliser que lorsqu'ils sont appropriés et qu'ils peuvent faire plus que simplement obtenir et définir des champs.

  • Vous ne pouvez avoir qu'un getter. Ensuite, la propriété est en lecture seule. Cela devrait en fait être le cas le plus courant.
  • Vous ne pouvez avoir qu'un setter, ce qui rend la propriété configurable, mais communiquant que rien d'autre ne devrait dépendre de sa valeur
  • Un getter peut calculer une valeur à partir de plusieurs champs plutôt que de renvoyer un seul champ.
  • Un getter peut faire une copie défensive
  • Un getter peut effectuer une opération de récupération coûteuse paresseusement et utiliser un champ pour mettre en cache la valeur
  • Un setter peut faire des vérifications d'intégrité et lancer IllegalArgumentException
  • Un setter peut informer les auditeurs des modifications apportées à la valeur
  • Vous pouvez avoir un setter qui définit plusieurs champs ensemble car ils appartiennent ensemble conceptuellement. Cela ne respecte pas la spécification JavaBeans, donc ne le faites pas si vous dépendez de frameworks ou d'outils qui attendent JavaBeans. Sinon, c'est une option utile.

Toutes ces choses sont des détails d'implémentation cachés derrière la simple interface "getter and setter". C'est à cela que sert l'encapsulation.

64
Michael Borgwardt

L'idée des getters et setters est de contrôler l'accès aux variables d'une classe. De cette façon, si la valeur doit être modifiée en interne pour être représentée d'une manière différente, vous pouvez le faire sans casser de code en dehors de la classe.

Par exemple, supposons que vous ayez une classe avec une variable de distance et qu'elle soit mesurée en pouces. Quelques mois passent, vous utilisez cette classe dans de nombreux endroits et vous réalisez soudainement que vous deviez représenter cette valeur en centimètres. Si vous n'utilisez pas de getter et de setter, vous devrez retrouver chaque utilisation de la classe et y convertir. Si vous avez utilisé un getter et un setter, vous pouvez simplement changer ces méthodes et tout ce qui utilise la classe ne se cassera pas.

public class Measurement
{

    /**
     * The distance in centimeters.
     */
    private double distance;

    /**
     * Gets the distance in inches.
     * @return A distance value.
     */
    public double getDistance()
    {
        return distance / 2.54;
    }

    /**
     * Sets the distance.
     * @param distance The distance, in inches.
     */
    public void setDistance(double distance)
    {
        this.distance = distance * 2.54;
    }
}
17
Robert Rouhani

Un bon avantage vient à l'esprit est que vous pouvez créer un champ ReadOnly en n'implémentant pas de setter pour ce champ particulier.

7
Sandeep Pathak

Voici l'inconvénient. Les Getters/Setters ont tendance à exposer les détails d'implémentation de votre classe au monde extérieur. Ce n'est pas une bonne chose. Imaginez que vous écrivez un progiciel de mécanique automobile. Ainsi, vous aurez besoin d'une classe de voiture, et donc vous exposez les getters et setters pour les champs

Date lastOilChangeDate;
int lastOilChangeMileage;

dans cette classe. En effet, le logiciel souhaite envoyer des e-mails lorsque les voitures des clients ont besoin de vidanges d'huile.

Mais que se passe-t-il lorsque de nouvelles voitures sortent où vous déterminez si une voiture a besoin d'une vidange d'huile différemment de "tous les 3000 miles ou 3 mois"? Peut-être que ces nouvelles voitures ont un capteur dans le carter d'huile qui mesure la saleté. De toute évidence, vous voudriez l'utiliser pour déterminer si un changement d'huile était nécessaire.

Le problème était que vous résolviez le mauvais problème avec ces getter/setters. Personne ne veut vraiment savoir quand a eu lieu le dernier changement d'huile, il veut savoir si vous en avez besoin d'un autre. Ce n'étaient que des détails d'implémentation, mais vous les avez intégrés à l'interface. Ce que vous auriez dû faire a été ajouté une méthode

public boolean needsOilChange() 

et puis la classe Car pourrait implémenter comme bon lui semble. Si l'algorithme change, la classe Mechanic n'aura pas à le faire car tout ce dont elle a besoin est la méthode needsOilChange.

3
MeBigFatGuy

Il n'y a rien de mal à en utilisant les getters et setters - sachez simplement que par en les utilisant et en les rendant tous publics, vous exposez vos variables et, d'une certaine manière, vous violez l'encapsulation . C'est ce que l'article que vous mentionnez essaie de mettre en garde - ne vous contentez pas de générer automatiquement des getters et setters pour toutes les variables d'instances privées; pensez à ce que vous souhaitez exposer à d'autres classes (et à quel niveau, c'est-à-dire privé/protégé/public) afin de ne l'exposer que si nécessaire.

2
Amos M. Carpenter