Encapsulation Java [dupliquer]


Cette question a déjà une réponse ici:

Nous disons toujours que les données seront encapsulées si nous définissons simplement des variables private et définissons des getters setters pour accéder à ces variables. Ma question est de savoir si nous pouvons accéder aux variables (données) via getters et setters, comment se fait-il que les données soient cachés ou de sécurité?

J'ai beaucoup cherché sur Google pour des explications mais je n'ai rien trouvé. chacun vient de dire dans ses blogs et ses messages qu'il s'agit d'une technique de dissimulation de données mais ne l'a pas expliquée/élaborée.

Impatient d'obtenir une explication appropriée et satisfaisante ici sur le forum de stackoverflow.

Author: Edwin Dalorzo, 2012-08-15

9 answers

La façon dont je comprends votre question est, bien que nous déclarons les variables comme private, car ces variables sont accessibles à l'aide de getters et setters, elles ne sont pas privées. Par conséquent, quel est le sens de faire cela?

Eh bien, lorsque vous utilisez getters et setters, vous pouvez restreindre l'accès aux variables private.

C'est-à-dire

private int x;

public int getInt(String password){
 if(password.equals("RealPassword")){
   return x;
  }
}

Et même chose pour les setters. Espérons que cette aide!

 14
Author: mithilatw, 2018-03-21 02:03:43

L'encapsulation ne se limite pas à définir des méthodes d'accesseur et de mutateur pour une classe. C'est un concept plus large de programmation orientée objet qui consiste à minimiser l'interdépendance entre les classes et il est généralement implémenté par le masquage d'informations.

La beauté de l'encapsulation est le pouvoir de changer les choses sans affecter ses utilisateurs.

Dans un langage de programmation orienté objet comme Java, vous réalisez l'encapsulation en masquant les détails en utilisant le modificateurs d'accessibilité (public, protégé, privé, plus aucun modificateur qui implique un package privé). Avec ces niveaux d'accessibilité, vous contrôlez le niveau d'encapsulation, moins le niveau est restrictif, plus le changement est coûteux lorsqu'il se produit et plus la classe est couplée avec d'autres classes dépendantes (c'est-à-dire les classes utilisateur, les sous-classes).

Par conséquent, l'objectif n'est pas de masquer les données elles-mêmes, mais l'implémentation détaille la façon dont ces données sont manipulées.

L'idée est de fournir une interface publique à travers laquelle vous avez accès à ces données. Vous pouvez ensuite modifier la représentation interne des données sans compromettre l'interface publique de la classe. Au contraire, en exposant les données elles-mêmes, vous compromettez l'encapsulation, et donc la capacité de changer la façon dont vous manipulez les données sans affecter ses utilisateurs. Vous créez une dépendance avec les données elles-mêmes, et non avec l'interface publique de la classe. Vous serait créer un cocktail parfait pour les problèmes lorsque le "changement" vous trouve enfin.

Il y a plusieurs raisons pour lesquelles vous pourriez vouloir encapsuler l'accès à vos champs. Joshua Bloch dans son livre Java efficace, au point 14: Minimiser l'accessibilité des classes et des membres, mentionne plusieurs raisons impérieuses, que je cite ici:

  • Vous pouvez limiter les valeurs qui peuvent être stockées dans un champ (c'est-à-dire que le sexe doit être F ou M).
  • Vous pouvez effectuer des actions lorsque le champ est modifié (événement déclencheur, valider, etc).
  • Vous pouvez assurer la sécurité des threads en synchronisant la méthode.
  • Vous pouvez passer à une nouvelle représentation de données (c'est-à-dire des champs calculés, un type de données différent)

Cependant, l'encapsulation est plus que masquer les champs. En Java, vous pouvez masquer des classes entières, en cachant ainsi les détails d'implémentation d'une API entière. Pensons, par exemple, dans la méthode Arrays.asList(). Il renvoie une implémentation List, mais vous ne vous souciez pas de l'implémentation, tant que comme il satisfait l'interface List, non?. L'implémentation peut être modifiée à l'avenir sans affecter les utilisateurs de la méthode.

La beauté de l'encapsulation

Maintenant, à mon avis, pour vraiment comprendre l'encapsulation, on doit d'abord comprendre l'abstraction.

Pensez, par exemple, au niveau d'abstraction dans le concept d'une voiture. Une voiture est complexe dans sa mise en œuvre interne. Ils ont plusieurs sous-système, comme un système de transmission, un système de freinage, un carburant système, etc.

Cependant, nous avons simplifié son abstraction, et nous interagissons avec toutes les voitures du monde à travers l'interface publique de leur abstraction. Nous savons que toutes les voitures ont un volant à travers lequel nous contrôlons la direction, elles ont une pédale qui lorsque vous appuyez dessus, vous accélérez la voiture et contrôlez la vitesse, et une autre qui lorsque vous appuyez dessus, vous la faites arrêter, et vous avez un levier de vitesses qui vous permet de contrôler si vous avancez ou reculez. Ces caractéristiques constituent le interface publique de l'abstraction de la voiture. Le matin, vous pouvez conduire une berline, puis en sortir et conduire un SUV l'après-midi comme si c'était la même chose.

Cependant, peu d'entre nous connaissent les détails de la façon dont toutes ces fonctionnalités sont implémentées sous le capot. Pensez à l'époque où les voitures n'avaient pas de système directionnel hydraulique. Un jour, les constructeurs automobiles l'ont inventé, et ils décident de le mettre dans des voitures à partir de là. Pourtant, cela n'a pas changé la façon dont les utilisateurs étaient en interagissant avec eux. Tout au plus, les utilisateurs ont constaté une amélioration de l'utilisation du système directionnel. Un changement comme celui-ci était possible parce que l'implémentation interne d'une voiture est encapsulée. Les modifications peuvent être effectuées en toute sécurité sans affecter son interface publique.

Maintenant, pensez que les constructeurs automobiles ont décidé de mettre le bouchon de carburant sous la voiture, et non dans l'un de ses côtés. Vous allez acheter une de ces voitures, et quand vous êtes à court d'essence, vous allez à la station d'essence, et vous ne trouvez pas la bouchon de réservoir de carburant. Soudain, vous réalisez qu'il est en dessous de la voiture, mais vous ne pouvez pas l'atteindre avec le tuyau de la pompe à essence. Maintenant, nous avons rompu le contrat d'interface publique, et donc, le monde entier se brise, il s'effondre parce que les choses ne fonctionnent pas comme prévu. Un tel changement coûterait des millions. Nous aurions besoin de changer toutes les pompes à essence dans le monde. Lorsque nous cassons l'encapsulation, nous devons payer un prix.

Donc, comme vous pouvez le voir, le but de l'encapsulation est de minimiser l'interdépendance et faciliter le changement. Vous maximisez l'encapsulation en minimisant l'exposition des détails d'implémentation. L'état d'une classe ne doit être accessible via son interface publique.

Je vous recommande vraiment de lire un article d'Alan Snyder intitulé Encapsulation and Inheritance in Object-Oriented programming Languages. Ce lien pointe vers le document original sur ACM, mais je suis sûr que vous pourrez trouver une copie PDF via Google.

 47
Author: Edwin Dalorzo, 2017-10-06 13:50:22

Les données sont sûres, car vous pouvez faire une logique supplémentaire dans votre getter / setter, et il n'est pas possible de changer les valeurs de votre variable. Imaginez que votre code ne fonctionne pas avec une variable null, donc dans votre setter, vous pouvez vérifier les valeurs null et attribuer une valeur par défaut qui est != NULL. donc, votre code fonctionne toujours, que quelqu'un essaie ou non de définir votre variable null.

 13
Author: markus, 2012-08-15 09:20:16

Ma question est de savoir si nous pouvons accéder aux variables( données) via getters et setters, comment se fait-il que les données soient cachées ou sûres?

Vous pouvez encapsuler la logique sous getters/setters par exemple

public void setAge(int age){
 if(age < 0){
  this.age = 0;
 }else{
  this.age = age;
 }
}
 5
Author: Jigar Joshi, 2012-08-15 09:17:52

Suite à la réponse de Jigar. Il y a quelques choses qui relèvent de l'encapsulation.

  1. Gestion des contrats: Si vous le faitespublic, vous obligez littéralement quiconque à le changer en ce qu'il veut. Vous ne pouvez pas le protéger en ajoutant une contrainte. Votre setter peut s'assurer que les données sont modifiées de manière appropriée.

  2. La Mutabilité: Vous n'avez pas toujours d'avoir un setter. S'il y a une propriété que vous vouliez garder immuable pour le la durée de vie de l'objet. Vous venez de le rendre privé et n'avez pas de setter pour cela. Il sera probablement défini via le constructeur. Ensuite, votre getter va juste retourner l'attribut (si c'est immuable) ou une copie de l'attribut (si l'attribut est mutable).

 4
Author: Nishant, 2012-08-15 09:24:59

En général, l'encapsulation des champs par les getters et les setters laisse plus de flexibilité pour les modifications.

Si les champs sont accessibles directement, vous êtes coincé avec "stupid fields". Les champs ne peuvent être écrits et lus que. Rien d'autre ne peut être fait lors de l'accès à un champ.

Lorsque vous utilisez des méthodes, vous pouvez faire ce que vous voulez lors de la définition / lecture de la valeur. Comme markus et Jigar l'ont mentionné, la validation est possible. De plus, vous pourriez décider un jour, que la valeur est dérivée d'un autre valeur ou certaines actions doivent être exécutées si la valeur change.

Comment se fait-il que les données soient cachées ou sécurisées

Les données ne sont ni cachées ni sûres en utilisant des getters et des setters. Cela vous donne juste la possibilité de le rendre sûr. Ce qui est caché, c'est l'implémentation et non les données.

 4
Author: Markus Kreusch, 2012-08-15 09:47:39

La validation des données est la réponse principale à votre question sur la façon dont l'encapsulation assure la sécurité s'il y a des accesseurs et/ou des mutateurs en jeu. D'autres l'ont mentionné en utilisant des exemples d'avoir une sécurité intégrée pour définir une valeur par défaut dans le mutateur. Vous avez répondu que vous préférez lancer des exceptions à la place, ce qui est génial, mais identifier que vous avez de mauvaises données lorsque vous allez les utiliser ne change pas le fait que vous avez de mauvaises données. Ne serait-il donc pas préférable d'attraper le exception avant que les données ne soient modifiées, c'est-à-dire le faire dans le mutateur? De cette façon, les données réelles ne sont jamais modifiées à moins que le mutateur ne les ait vérifiées comme étant valides, ainsi les données d'origine sont conservées en cas de mauvaises données.

Je ne suis encore qu'un étudiant moi-même, mais j'avais exactement la même chose que vous quand j'ai rencontré l'encapsulation pour la première fois, alors j'ai passé du temps à le comprendre.

 2
Author: Grim0013, 2013-06-06 06:11:04

J'aime l'explication lors de la prise en compte des Threads. Si vous avez rendu vos champs publics, comment votre instance va-t-elle savoir quand un certain Thread a changé l'un de ses champs? La seule façon de le faire serait avec l'encapsulation, ou plus simplement put donner des getters et des setters à ce champ, donc vous TOUJOURS savez et pouvez vérifier/réagir aux mises à jour des champs par exemple.

 1
Author: Eugene, 2012-08-15 09:22:04

L'encapsulation rend le code plus facile à réutiliser par d'autres personnes. Une autre raison clé d'utiliser l'encapsulation est que les interfaces ne peuvent pas déclarer de champs, mais elles peuvent déclarer des méthodes, qui peuvent faire référence à un champ!

Les méthodes sont correctement nommées avec un verbe au début. Comme: getName(),setName (), isDying (). Ce qui peut aider à lire le code!

 0
Author: blockay, 2015-07-25 07:05:57