À quoi servent les getters et les setters? [dupliquer]
possibilité de duplication:
Pourquoi utiliser getters et setters?
j'ai lu des livres sur Java
, disant qu'il est bon de créer des setters et des getters pour des variables telles que x
et y
. Par exemple:
public int getX(){
return x;
}
public void setX(int x){
this.x = x;
}
mais quelle est la différence entre cela et
...(shape.x)... // basically getX()
et
shape.x = 90; // basically setX()
si setters et getters sont meilleurs, pourriez-vous m'expliquer quels problèmes pratiques se poseraient?
13 réponses
de Multiples raisons:
-
Si vous autorisez l'accès à un champ comme
de forme.x = 90
alors vous ne pouvez pas ajouter de logique à l'avenir pour valider les données.
dire si x ne peut pas être moins de 100 vous ne pouvez pas le faire, cependant si vous aviez des setters comme
public void setShapeValue(int shapeValue){
if(shapeValue < 100){
//do something here like throw exception.
}
}
- Vous ne pouvez pas ajouter quelque chose comme la copie sur écriture logique (voir CopyOnWriteArrayList )
- une autre raison est que pour accéder à des champs en dehors de votre classe, vous devrez les marquer publiquement, protégés ou par défaut, et vous perdrez ainsi le contrôle. Lorsque les données sont très internes à la classe de rupture Encapsulation et en général OOPS méthodologie.
mais pour des constantes comme
public final String SOMETHING = "SOMETHING";
autoriser l'accès aux champs car ils ne peuvent pas être changés, par exemple variable, vous les placerez avec getters, setters.
- un autre scénario est quand vous voulez que votre classe soit immuable, si vous autorisez l'accès au champ alors vous brisez l'immuabilité de votre classe puisque les valeurs peuvent être changées. Mais si vous concevez soigneusement votre classe avec getters et aucun setters, vous gardez l'immuabilité intacte.
bien que dans de tels cas, vous devez soyez prudent dans la méthode getter pour vous assurer que vous ne donnez pas de référence des objets(dans le cas où votre classe A objet comme instances).
nous pouvons utiliser les variables privées dans n'importe quel paquet en utilisant getters et setters.
utilisant les fonctions getter et setter permettent des contraintes et l'encapsulation. Disons que x est le rayon. forme.x = -10 n'aurait pas beaucoup de sens. Aussi, si quelqu'un tente de définir une valeur illégale, vous pouvez imprimer une erreur, définissez une valeur par défaut, ou ne rien faire.
il est de bonne pratique de rendre les variables membres privées afin qu'elles ne puissent pas être modifiées directement par des programmes qui les utilisent.
beaucoup de gens ont mentionné encapsuler les détails de la mise en œuvre, qui pour moi est la plus grande raison d'utiliser getters et setters dans une classe. Avec cela, vous obtenez également beaucoup d'autres avantages, notamment la possibilité de jeter et remplacer la mise en œuvre sur un coup de tête sans avoir besoin de toucher chaque morceau de code qui utilise votre classe. Dans un petit projet, ce n'est pas un grand avantage, mais si votre code finit par être une bibliothèque bien utilisée (interne ou publique), il peut être énorme bénéficier.
Un exemple précis: nombres complexes en mathématiques . Certaines langues en font une langue ou une caractéristique de cadre, d'autres non. J'utiliserai une classe mutable comme exemple ici, mais elle pourrait tout aussi bien être immuable.
un nombre complexe peut être écrit sur la forme a + bi
avec des parties réelles et imaginaires, se prêtant bien à [gs]etRealPart
et [gs]etImaginaryPart
.
cependant , dans certains cas il est plus facile de raisonner des nombres complexes sur la forme polaire re^(iθ)
, donnant [gs]etRadius
(r) et [gs]etAngle
(θ).
vous pouvez également exposer des méthodes comme [gs]etComplexNumber(realPart, imaginaryPart)
et [gs]etComplexNumber(radius, angle)
. Selon les types d'argument, ceux-ci peuvent ou ne peuvent pas avoir besoin de noms différents, mais alors la classe' consommateur peut utiliser l'un ou l'autre comme il convient à ses besoins.
Les deux formes sont interchangeables, vous pouvez assez facilement convertir de l'un à l'autre, ce qui forme la classe utilise pour le stockage interne n'est pas pertinent pour les consommateurs de cette classe. Toutefois, les consommateurs peuvent utiliser l'une ou l'autre forme. Si vous choisissez la forme a+bi pour la représentation interne, et exposer que l'utilisation des champs plutôt que getters et setters , non seulement vous forcez les consommateurs de la classe à utiliser cette forme, vous ne pouvez pas non plus facilement changer d'avis plus tard et remplacer la représentation interne par re^(iθ) parce que cela s'avère être plus facile à mettre en œuvre dans votre scénario. Vous êtes bloqué avec l'API publique que vous avez définie, qui exige que spécifiquement les parties réelles et imaginaires soient exposées en utilisant des noms de champ spécifiques.
une autre bonne raison d'utiliser getter et setter peut être comprise par l'exemple suivant ""
public class TestGetterSetter{
private String name ;
public void setName(String name){
this.name = name ;
}
public String getName(String name){
return this.name ;
}
}
le point de getters et setters est que seulement ils sont destinés à être utilisés pour accéder à la varialble privée, qu'ils obtiennent ou placent. De cette façon, vous fournissez encapsulation et il sera beaucoup plus facile de remanier ou modifier votre code plus tard.
Imaginez que vous utilisez le nom au lieu de son getter. Alors si vous voulez ajouter quelque chose comme un par défaut (disons que le nom par défaut est 'Guest' s'il n'a pas été défini avant), alors vous devrez modifier à la fois la fonction getter et la fonction sayName.
public class TestGetterSetter{
private String name ;
public void setName(String name){
this.name = name ;
}
public String getName(String name){
if (this.name == null ){
setName("Guest");
}
return this.name ;
}
}
il n'est pas nécessaire que getters et setter commencent par get et set - ce sont juste des fonctions normales de membre. Mais c'est une convention de faire ça. (surtout si vous utilisez Java Beans)
L'une des meilleures raisons pour lesquelles je peux penser à getters et setters est la permanence de L'API d'une classe. Dans les langages comme python, vous pouvez accéder aux membres par leur nom et les basculer vers des méthodes plus tard. Parce que les fonctions se comportent différemment que les membres en java une fois que vous accédez à une propriété thats it. La restriction de sa portée brise plus tard le client.
en fournissant des getters et des setters un programmeur a la flexibilité de modifier les membres et le comportement librement aussi longtemps que le respecter le contrat décrit par l'API publique.
disons, hypothétiquement, que vous trouvez une bibliothèque qui fait un meilleur travail de ce que vous avez fait dans votre propre classe (Votreclasse). La chose naturelle à faire à ce point est de faire de Votreclasse une interface de wrapper à cette bibliothèque. Il a encore un concept de "X" que votre code client doit obtenir ou Définir. Naturellement, à ce stade, vous devez écrire les fonctions d'accesseur.
si vous avez négligé d'utiliser les fonctions accessor et de laisser votre code client accéder YourClass.x directement, vous devriez maintenant réécrire tout votre code client qui a touché votre classe.x. Mais si vous utilisiez votre classe.getX () et Votreclasse.setX () dès le début, vous n'aurez besoin que de réécrire Votreclasse.
L'un des concepts clés de la programmation, et en particulier de la programmation orientée objet, est de cacher les détails de la mise en œuvre afin qu'ils ne soient pas utilisés directement par le code dans d'autres classes ou modules. De cette façon, si vous changez les détails de la mise en œuvre (comme dans l'exemple ci-dessus), le code client ne connaît pas la différence et ne doit pas être modifié. Pour tous votre code client sait, "x" peut être une variable ou une valeur calculée à la volée.
c'est une simplification excessive et ne couvre pas tous les scénarios où cacher l'implémentation est bénéfique, mais c'est l'exemple le plus évident. Le concept de cacher les détails de la mise en œuvre est assez fortement lié à L'OOP maintenant, mais vous pouvez trouver des discussions ça remonte à des décennies avant que OOP ne soit imaginé. Il remonte à l'un des concepts de base du développement logiciel, qui est de prendre un grand problème nébuleux, et de le diviser en petits problèmes bien définis qui peuvent être résolus facilement. Les fonctions d'accesseur aident à garder vos petites sous-tâches séparées et bien définies: moins vos classes en savent sur les tâches internes des autres, mieux c'est.
à l'Origine, les getter/setter modèle a été créé pour promouvoir la bonne conception orientée objet par encapsulating
à l'intérieur d'un class
extérieurs interface
.
- Cacher la représentation interne de la propriété
c'est la meilleure réponse à la question Pourquoi utiliser les accesseurs et mutateurs?
Il y a beaucoup de raisons. Voici quelques-uns.
- les accesseurs, les getters en particulier, apparaissent souvent dans les interfaces. Vous ne pouvez pas spécifier une variable membre dans une interface.
- une fois que vous exposez cette variable membre, vous ne pouvez pas changer d'avis sur la façon dont elle est mise en œuvre. Par exemple, si vous voyez un besoin plus tard de passer à un modèle comme l'agrégation, où vous voulez que la propriété" x " Vienne réellement d'un objet imbriqué, vous finissez par devoir copier cette valeur et essayer de la synchroniser. Pas bonne.
- la plupart du temps vous êtes bien mieux lotis pas exposer le setter. Tu ne peux pas faire ça avec des champs publics comme x.
avant d'entrer dans la réponse, nous devons savoir quelque chose avant...! " JavaBeans ".
JavaBeans sont des classes java qui ont des propriétés . Pour notre but, pensez aux propriétés comme des variables d'instance privée. puisqu'ils sont privés, le seul moyen d'y accéder
de l'extérieur de leur classe est par des "méthodes" de la classe.
Les méthodes qui changent la valeur d'une propriété sont appelées les méthodes de setter , et les méthodes qui extraient la valeur d'une propriété sont appelées méthodes de getter .
je dirais que ni les getters/setters ni les membres du public ne sont un bon design orienté objet. Ils cassent tous les deux L'Encapsulation OOP en exposant les données d'un objet au monde qui ne devrait probablement pas accéder aux propriétés de l'objet en premier lieu.
ceci est fait en appliquant le encapsulation principe de OOP.
un mécanisme de langage pour restreindre l'accès à certains composants de l'objet.
cela signifie que vous devez définir la visibilité pour les attributs et les méthodes de vos classes. Il y a 3 visibilités communes:
- privé: seule la classe peut voir et utiliser les attributs/méthodes.
- Protégés: Seule la classe et ses enfants peuvent voir et utiliser les attributs/méthodes.
- Public: chaque classe peut voir et utiliser les attributs/méthodes.
lorsque vous déclarez des attributs privés/protégés, vous êtes encouragés à créer des méthodes pour obtenir la valeur (get) et changer la valeur (set). Un exemple de visibilité est la classe [ArrayList][2]
: elle possède une propriété size
pour connaître la taille réelle de la intérieur de la matrice. Seule la classe doit changer sa valeur, donc le code est quelque chose comme
public class ArrayList<E> {
private int size;
private Object[] array;
public getSize() {
return this.size;
}
public void add(E element) {
//logic to add the element in the array...
this.size++;
}
}
dans cet exemple, vous pouvez voir que la valeur de taille ne peut changer qu'à l'intérieur des méthodes de classe, et vous pouvez obtenir la taille réelle en l'appelant dans votre code (ne pas la muter):
public void someMethod() {
List<String> ls = new ArrayList<String>();
//adding values
ls.add("Hello");
ls.add("World");
for(int i = 0; i < ls.size(); i++) {
System.out.println(ls.get(i));
}
}
Getters et les setters encapsuler les champs d'une classe en les rendant accessibles uniquement par le biais de ses méthodes publiques et de garder les valeurs elles-mêmes privé. C'est considéré comme un bon Principe D'OO.
D'accord, il semble souvent comme le code redondant si elle ne fait rien de plus que de définir ou de retourner une valeur. Cependant, les setters vous permettent également de faire la validation des entrées ou le nettoyage. Avoir cela dans un endroit améliore l'intégrité des données pour vos objets,
parce que nous utilisons un langage de programmation orienté objet. Nous utilisons ici la dissimulation et l'encapsulation de données. La variable ne doit pas être directement accessible à partir de l'extérieur du monde (pour la réalisation de la dissimulation des données) de sorte que nous allons La créer privée so
de forme.x
n'est pas correct. Les méthodes Getter et setter sont utilisées pour obtenir et définir la valeur de x qui est la façon d'obtenir l'encapsulation.