Duplicate possible:
Pourquoi utiliser les getters et les 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 les setters et les getters sont meilleurs, pouvez-vous m'expliquer quels problèmes pratiques se poseraient?
Plusieurs raisons:
Si vous autorisez l'accès aux champs comme
shape.x = 90
dans ce cas, vous ne pourrez plus ajouter de logique pour valider les données.
dire si x ne peut pas être inférieur à 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.
}
}
Bien que pour des constantes comme
public final String SOMETHING = "SOMETHING";
vous autoriserez l'accès aux champs car ils ne peuvent pas être modifiés, par exemple, vous allez les placer avec des accesseurs, des setters.
Cependant, dans de tels cas, vous devez faire attention à la méthode getter pour vous assurer de ne pas donner de référence aux objets (au cas où votre classe aurait des objets comme instances).
Nous pouvons utiliser les variables privées dans n’importe quel paquet en utilisant des accesseurs.
L'utilisation des fonctions getter et setter permet des contraintes et une encapsulation. Disons que x est le rayon. shape.x = -10 n'aurait pas beaucoup de sens. De plus, si quelqu'un essaie de définir une valeur illégale, vous pouvez imprimer une erreur, définir une valeur par défaut ou ne rien faire.
Il est recommandé de rendre les variables de membre privées afin qu'elles ne puissent pas être modifiées directement par les programmes qui les utilisent.
Beaucoup de gens ont mentionné résumer les détails de la mise en œuvre, ce qui est pour moi la principale raison d'utiliser des accesseurs et des passeurs dans une classe. Avec cela, vous bénéficiez également de nombreux autres avantages, notamment la possibilité de rejeter et de remplacer l’implémentation sur un coup de tête sans avoir à toucher à tous les éléments de code qui utilisent votre classe. Dans un petit projet, ce n'est pas un gros avantage, mais si votre code finit par être une bibliothèque bien utilisée (interne ou publique), il peut s'agir d'une énorme avantage.
Un exemple spécifique: nombres complexes en mathématiques. Certaines langues les utilisent comme langage ou structure, d'autres pas. Je vais utiliser une classe mutable comme exemple ici, mais elle pourrait tout aussi bien être immuable.
Un nombre complexe peut être écrit sur le formulaire 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 sur les nombres complexes sous la forme polaire re^(iθ)
, en donnant [gs]etRadius
(R) et [gs]etAngle
(Θ).
Vous pouvez également exposer des méthodes telles que [gs]etComplexNumber(realPart, imaginaryPart)
et [gs]etComplexNumber(radius, angle)
. En fonction des types d'arguments, ceux-ci peuvent ou non avoir besoin de noms différents, mais le consommateur de la classe peut alors utiliser l'un ou l'autre selon ses besoins.
Les deux formes sont interchangeables. vous pouvez assez facilement convertir de l'un à l'autre, la forme utilisée par la classe pour le stockage interne n'a donc aucune importance pour les utilisateurs de cette classe. Toutefois, les consommateurs peuvent utiliser l’une ou l’autre des deux formes. Si vous choisissez la forme a + bi pour la représentation interne et que l'exposez à l'aide de champs plutôt que de getters et de setters , vous ne forcez pas uniquement les consommateurs de classe à: Si vous utilisez cette forme, vous ne pourrez plus, par la suite, changer facilement d’idée et remplacer la représentation interne par re ^ (iθ), car cela s’avère plus facile à implémenter dans votre scénario particulier. Vous êtes coincé avec l'API publique que vous avez définie, qui spécifie que les parties réelles et imaginaires sont exposées à l'aide de noms de champs spécifiques.
L’exemple suivant constitue une autre bonne raison d’utiliser getter et setter.
public class TestGetterSetter{
private String name ;
public void setName(String name){
this.name = name ;
}
public String getName(String name){
return this.name ;
}
}
L'intérêt des accesseurs et des setters est que seuls ceux-ci sont destinés à être utilisés pour accéder à la variable privée qu'ils obtiennent ou définissent. De cette façon, vous fournissez une encapsulation et il sera beaucoup plus facile de refactoriser ou de modifier votre code ultérieurement.
Imaginez que vous utilisiez name au lieu de son getter. Ensuite, si vous souhaitez ajouter quelque chose comme une valeur par défaut (disons que le nom par défaut est 'Invité' s'il n'a pas été défini auparavant), vous devrez alors modifier les fonctions getter et 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 les accesseurs et les passeurs commencent par get et set - ce ne sont que des fonctions membres normales. Cependant, c'est une convention pour le faire. (surtout si vous utilisez Java Beans)
L'une des meilleures raisons pour laquelle je peux penser aux accesseurs et aux setters est la permanence de l'API d'une classe. Dans des langages comme python, vous pouvez accéder aux membres par leur nom et les basculer ultérieurement vers des méthodes. Car les fonctions se comportent différemment des membres dans Java une fois que vous avez accédé à une propriété Le fait de restreindre son étendue par la suite casse le client.
En fournissant des getters et des setters, un programmeur a la possibilité de modifier les membres et le comportement librement tant que le contrat est décrit par l’API publique.
Supposons, hypothétiquement, que vous trouviez une bibliothèque qui fasse un meilleur travail que ce que vous avez fait dans votre propre classe (YourClass). La chose naturelle à faire à ce stade est de faire de YourClass une interface wrapper vers cette bibliothèque. Il a toujours un concept de "X" que votre code client doit obtenir ou définir. Naturellement, à ce stade, vous devez à peu près écrire les fonctions d’accesseur.
Si vous avez négligé d'utiliser les fonctions d'accesseur et laissé votre code client accéder directement à YourClass.x, vous devez maintenant réécrire tout votre code client ayant jamais touché YourClass.x. Mais si vous utilisiez YourClass.getX () et YourClass.setX () depuis le début, il vous suffira de réécrire YourClass.
L'un des concepts clés de la programmation, et en particulier de la programmation orientée objet, consiste à masquer les détails d'implémentation afin qu'ils ne soient pas utilisés directement par le code dans d'autres classes ou modules. Ainsi, si vous modifiez les détails d'implémentation (comme dans l'exemple ci-dessus), le code client ne connaît pas la différence et ne doit pas être modifié. Pour tout ce que votre code client sait, "x" peut être une variable ou une valeur calculée à la volée.
Ceci est une simplification excessive et ne couvre pas tous les scénarios dans lesquels cacher la mise en œuvre est bénéfique, mais c'est l'exemple le plus évident. Le concept de masquer les détails de la mise en oeuvre est assez étroitement lié à OOP maintenant, mais vous pouvez en trouver des discussions remontant à plusieurs décennies auparavant OOP a été imaginé. Il va Revenons à l’un des concepts clés du développement logiciel, qui consiste à prendre un gros problème nébuleux et à 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 sauront sur leurs internes, mieux ce sera.
A l'origine, le motif getter/setter avait été créé pour promouvoir une bonne conception orientée objet par encapsulating
les éléments internes d'un class
à partir de son externe interface
.
c’est la meilleure réponse de votre question Pourquoi utiliser les getters et les setters?
Avant d'entrer dans la réponse, nous devons savoir quelque chose avant ...! "JavaBeans".
Les JavaBeans sont des classes Java qui possèdent des propriétés . Considérons les propriétés comme des instances privées. Dans la mesure où elles sont privées, la seule façon d’y accéder de l’extérieur de leur classe consiste à utiliser des "méthodes" dans la classe.
Les méthodes qui modifient la valeur d'une propriété sont appelées méthodes de définition, et les méthodes qui extraient la valeur d'une propriété sont appelées méthodes de collecte.
Il y a beaucoup de raisons. En voici quelques exemples.
Je dirais que ni les getters/setters ni les membres du public ne sont bons en conception orientée objet. Ils cassent tous les deux OOP Encapsulation en exposant au monde des données d'objets qui ne devraient probablement pas accéder aux propriétés de l'objet en premier lieu.
Ceci est fait en appliquant le principe d'encapsulation de la POO.
Un mécanisme de langage pour restreindre l'accès à certains composants de l'objet.
Cela signifie que vous devez définir la visibilité des attributs et des méthodes de vos classes. Il y a 3 visibilités communes:
Lorsque vous déclarez des attributs privés/protégés, vous êtes invité à créer des méthodes pour obtenir la valeur (get) et modifier la valeur (définie). Un exemple de visibilité est le [ArrayList][2]
class: il possède une propriété size
pour connaître la taille réelle du tableau interne. Seule la classe doit changer sa valeur, le code ressemble donc à 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 la taille ne peut changer que dans les méthodes de la classe et vous pouvez obtenir la taille réelle en l'appelant dans votre code (sans la modifier):
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));
}
}
Les Getters et les setters encapsulent les champs d'une classe en les rendant accessibles uniquement via ses méthodes publiques et en préservant la confidentialité des valeurs. Cela est considéré comme un bon OO principe.
Certes, il semble souvent que le code soit redondant s’il ne fait rien de plus que définir ou renvoyer une valeur. Cependant, les configurateurs vous permettent également de valider ou de nettoyer les entrées. Avoir cela au même 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 le masquage et l’encapsulation de données. La variable ne doit pas être directement accessible de l’extérieur (pour masquer les données), nous allons donc la créer de manière privée.
forme.x
n'est pas correcte. Les méthodes Getter et Setter sont utilisées pour obtenir et définir la valeur de x qui est le moyen d’atteindre l’encapsulation.