Au sein d' un paradigme de conception orientée objet, les choses ne doivent pas être en train de modifier des objets en dehors de l'objet lui - même. Toute modification de l'état d'un objet doit être effectuée via des méthodes sur l'objet.
Ainsi, en void predictPrice(Item item)
tant que fonction membre d'une autre classe, c'est faux . Cela aurait pu être acceptable à l'époque de C, mais pour Java et C ++, les modifications d'un objet impliquent un couplage plus profond avec l'objet qui entraînerait probablement d'autres problèmes de conception en cours de route (lorsque vous refactorisez la classe et modifiez ses champs, maintenant que «PredictPrice» doit être remplacé par dans un autre fichier.
De retour en arrière d' un nouvel objet, ne dispose pas des effets secondaires associés, le paramètre est passé dans pas changé. Vous (la méthode PredictPrice) ne savez pas où ce paramètre est utilisé. La Item
clé d'un hachage est-elle quelque part? avez-vous changé son code de hachage en faisant cela? Est-ce que quelqu'un d'autre s'y accroche s'attend à ce qu'il ne change pas?
Ces problèmes de conception suggèrent fortement que vous ne devriez pas modifier des objets (je plaiderais pour l'immuabilité dans de nombreux cas), et si vous le faites, les modifications de l'état devraient être contenues et contrôlées par l'objet lui-même plutôt que quelque chose sinon en dehors de la classe.
Regardons ce qui se passe si l'on tripote les champs de quelque chose dans un hachage. Prenons un peu de code:
import java.util.*;
public class Main {
public static void main (String[] args) {
Set set = new HashSet();
Data d = new Data(1,"foo");
set.add(d);
set.add(new Data(2,"bar"));
System.out.println(set.contains(d));
d.field1 = 2;
System.out.println(set.contains(d));
}
public static class Data {
int field1;
String field2;
Data(int f1, String f2) {
field1 = f1;
field2 = f2;
}
public int hashCode() {
return field2.hashCode() + field1;
}
public boolean equals(Object o) {
if(!(o instanceof Data)) return false;
Data od = (Data)o;
return od.field1 == this.field1 && od.field2.equals(this.field2);
}
}
}
ideone
Et j'admets que ce n'est pas le plus grand code (accéder directement aux champs), mais il sert son objectif de démontrer un problème avec les données mutables utilisées comme clé d'un HashMap, ou dans ce cas, simplement mises dans un HashSet.
La sortie de ce code est:
true
false
Ce qui s'est passé, c'est que le hashCode utilisé lors de son insertion est l'endroit où l'objet se trouve dans le hachage. La modification des valeurs utilisées pour calculer le hashCode ne recalcule pas le hachage lui-même. C'est un danger de mettre n'importe quel objet mutable comme clé d'un hachage.
Ainsi, pour revenir à l'aspect original de la question, la méthode appelée ne "sait" pas comment l'objet qu'elle obtient en tant que paramètre est utilisé. Fournir la « permet de muter l'objet » comme la seule façon de faire cela signifie qu'il ya un certain nombre de bugs subtils qui peuvent se glisser. Comme perdre des valeurs dans un hachage ... sauf si vous ajoutez plus et le hachage gets rabâché - moi confiance , c'est un bug méchant à traquer (j'ai perdu la valeur jusqu'à ce que j'ajoute 20 autres éléments à la hashMap et puis soudain, il réapparaît).
- À moins qu'il n'y ait de très bonnes raisons de modifier l'objet, renvoyer un nouvel objet est la chose la plus sûre à faire.
- Quand il est une bonne raison de modifier l'objet, cette modification doit être effectuée par l'objet lui - même (invoquant des méthodes) plutôt que par une fonction externe qui peut tourner ses champs.
- Cela permet de refaçonner l'objet avec un coût de maintenance moindre.
- Cela permet à l'objet de s'assurer que les valeurs qui calculent son code de hachage ne changent pas (ou ne font pas partie de son calcul de code de hachage)
Connexe: Écraser et renvoyer la valeur de l'argument utilisé comme conditionnel d'une instruction if, à l'intérieur de la même instruction if