web-dev-qa-db-fra.com

Conventions Java: utiliser des getters/setters DANS la classe?

Mon professeur insiste vraiment sur la protection contre les fuites dans la vie privée en utilisant toujours des accesseurs et des mutateurs pour accéder aux variables d'instance privées; Cependant, dois-je utiliser les getters/setters d'une classe dans la classe?

Donc, par exemple, si j'ai la classe suivante:

public class Person 
{
    private String name;
    private int age;
}

et je veux écrire une méthode toString () pour cela. Puis-je simplement écrire:

public String toString()
{
    return name + " " + age;
}

OU dois-je faire quelque chose comme ça:

public String toString()
{
    return this.getName() + " " + this.getAge();
}
44
LTH

Vous POUVEZ faire l'un ou l'autre. Cependant, votre professeur pourrait apprécier d’utiliser les méthodes au lieu de l’accès direct. Voici pourquoi.

Disons que vous avez un cours comme celui-ci:

class SomeClass {
    private int someValue;
    private String someString;

    public SomeClass(int someValue, String someString) {
        this.someValue = someValue;
        this.someString = someString;
    }

    public int someValue() {
        return someValue;
    }

    public int someString() {
        return someString;
    }

    public String toString() {
        return someValue + ": " + someString;
    }

}

C'est assez simple, non? Eh bien, si, tout à coup, nous voulions CHANGER la mise en œuvre de la façon dont nous calculons someValue et la baser sur someString:

public int someValue() {
    int value = 0;
    for(int i = 0; i < someString.length; i++) {
         if(someString.charAt(i) == ' ') value++;
    }
    return value;
}

Maintenant, vous devez aussi changer chaque endroit où la variable someValue a été utilisée.

Donc, si vous voulez que le code soit plus facile à gérer à long terme, utilisez les appels de méthodes. Ainsi, lorsque vous modifiez des modifications de code sur vous (et croyez-moi, cela change tout le temps), il vous suffit de le changer à un endroit au lieu de deux.

Et oui, vous voudriez utiliser un appel de méthode pour obtenir someString à la place de l'accès direct dans la dernière méthode :-)

34
corsiKa

Lorsque je conçois une classe, j'essaie de faire une distinction claire entre l'intérieur (détails de mise en œuvre) et l'extérieur (l'interface exposée au monde). Les getters et les setters constituent un endroit pratique pour convertir des valeurs entre la forme dans laquelle elles sont stockées dans les membres d'instance de l'objet et la forme dans laquelle le monde extérieur les voit. Utiliser des getters et des setters en interne serait une bonne solution, car ils seraient utilisés à la fois par l'intérieur et par l'extérieur. 

Si vous souhaitez masquer une partie d'une classe d'une autre partie de la même classe, envisagez de séparer la partie que vous souhaitez masquer dans sa propre classe.

Ce n'est normalement pas une bonne idée, pour plusieurs raisons:

  • Vous pouvez même ne pas vouloir d'accesseurs pour tous les champs
  • Certains accesseurs peuvent faire une copie défensive afin de ne pas exposer l'état interne. Ceci est normalement inutile dans la classe où vous savez que vous n'allez pas le modifier - ou tout simplement faux si vous savez que vous allez le modifier.
  • Cela rend le débogage plus ennuyeux, car vous devez suivre les getters/setters
  • Cela rend la lecture du code plus difficile dans la plupart des IDE, car la plupart d’entre eux colorent les champs différemment des variables locales.

... mais comme toujours, il y a des exceptions. Certains setters peuvent avoir des effets secondaires (par exemple définir une seconde valeur) que vous voulez exécuter, alors il peut être préférable d'utiliser le setter. De même, si vous concevez votre classe pour l'héritage, il peut être préférable de passer par un accesseur si vous souhaitez que la sous-classe puisse modifier le comportement.

13
waxwing

En général non. Si votre getter renvoie autre chose que la valeur du champ, vous devez utiliser la méthode, mais dans ce cas rare, votre méthode devrait avoir un nom plus descriptif. Pour un mauvais exemple, si vous avez:

public void setName(String name)
{
  _name = name;
}

et votre getter a renvoyé quelque chose d'autre, comme

public String getName()
{
  return _name.toUpperCase();
}

alors oui, vous devriez utiliser le getter. Il serait toutefois préférable d’avoir un nom plus descriptif pour ce getter:

public String getNameAsUppercase()
{
  return _name.toUpperCase();
}
7
Paul

Vous pouvez utiliser les accesseurs et les mutateurs, mais c'est un standard compliqué à suivre.

Cela encombrerait votre code et dérouterait quiconque essaierait de le lire en pensant que cela ne ferait peut-être pas partie de votre classe.

Fondamentalement, il suffit d’accéder aux variables directement depuis votre classe et indirectement depuis n’importe où.

5
Jon Egeland

Non, tu ne le fais pas. Vous pouvez accéder à toutes les variables, privées, publiques ou protégées, à partir de la classe.

Voici quelques tableaux pour vous aider:

enter image description here

Source: Tutoriels Java

5
eboix

D'un autre côté, considérez-le du point de vue de la conception. L'une des motivations des accesseurs/configurateurs est que le stockage de données sous-jacent peut changer et que les éléments qui implémentent la classe ne doivent pas nécessairement être modifiés car celle-ci est encapsulée.

Donc, gardez cela à l'esprit, l'utilisation de getters/setters au sein de la classe facilite les changements futurs. Au lieu d'avoir à rechercher tous les lieux qui modifient le membre directement, il vous suffit de changer le getter/setter. En fonction de la complexité de la classe, cela peut réduire considérablement la quantité de travail nécessaire pour changer les membres de stockage. 

Par exemple, supposons que vous commenciez avec la variable d’âge en années. Ensuite, vous décidez plus tard de l’enregistrer en secondes pour une raison quelconque. Mais vous voulez toujours l’imprimer en années quand même. Ainsi, dans votre exemple, vous pouvez faire le calcul dans votre fonction toString () (et partout où vous voulez des années en unités) ou vous pouvez simplement changer le calcul dans la routine getAge () pour renvoyer des années à partir des secondes et rien d'autre n'a changer. 

Évidemment, cet exemple est un peu trivial. Plus la classe est compliquée, plus il est utile d’utiliser des getters/setters. 

3
tpg2114

Si votre classe (ou les méthodes d'accès en question) n'est pas final, vous devez absolument utiliser les méthodes d'accès.

Si une autre classe étend la vôtre et remplace ces accesseurs, votre classe doit utiliser les accesseurs remplacés. Si cela casse votre super-classe, votre super-classe est mal conçue; évitez que ces accesseurs ne soient remplacés par final ou modifiez la conception de votre classe.

3
erickson

Non, vous pouvez utiliser directement vos variables d'instance dans la classe, vous ne violez aucune "règle". Les getters et les setters sont obligatoires pour les autres classes pour accéder aux variables d'instance d'une classe afin de ne pas violer le principe d'encapsulation (ce qui est très important dans la programmation OO).

En fin de compte, c'est une question de choix, mais vous enregistrez une méthode avec votre premier exemple.

1
talnicolas

S'il existe des getters et des setters, alors ils devraient toujours être utilisés, même en classe. Bien sûr, si getter et setter font quelque chose de plus en méthode, alors il faut en tenir compte si cela répond aux besoins.

Devrait être utilisé pas moyen doit être utilisé. La propriété peut être utilisée directement (à l'intérieur de la classe si la propriété est privée - et devrait l'être), mais il est de pratique d'utiliser getter et setter.

Donc, utiliser une propriété directement est possible, mais je recommande d'utiliser get et set car cela donne plus de flexibilité et permet de faire plus que donner ou obtenir des informations.

Par exemple, si en premier lieu, le setter ne définit que quelque chose, mais après un certain temps, le setter est modifié pour faire quelque chose de plus.

 setName(name){

     this.name=name;
 }

Donc, dans le code setName("John"); est égal à name="John". Mais imaginons qu'après un certain temps, nous souhaitons définir une autre propriété lorsque name est défini:

 setName(name){

     this.name=name;
     this.nameIsSet=true;
 }

autre exemple (modèle d'écoute) :

setName(name){

     this.name=name;
     this.listener.nameChanged(this.name); //we call listener that variable changed
 }

Ensuite, le programmeur doit trouver chaque affectation telle que name="John" en classe et la refactoriser au nouveau comportement. Si seulement setName est utilisé, aucun changement de code ne doit être effectué.

Bien sûr, tout dépend des besoins et il est possible que le fait de créer une propriété de l’extérieur fasse quelque chose de plus et de différent et ne répond pas à nos besoins en classe.

1
Maciej Sikora

Je pense que nous devrions utiliser getters () et setters () au lieu d’accéder directement. cela facilite également le débogage. Par exemple, si vous devez attribuer un emplacement multiple variable à votre classe et que vous souhaitez rechercher plus tard le nombre d'emplacements affectés à la variable, vous devez rechercher l'ensemble de l'affectation et définir le point d'arrêt.

mais si vous utilisez un setter, vous pouvez simplement mettre un point d'arrêt dans la méthode setter et voir combien de fois la variable est affectée. 

0
Sharif