Le strutture hanno il loro posto, anche in Java. Dovresti usarli solo se le seguenti due cose sono vere:
- Hai solo bisogno di aggregare i dati che non hanno alcun comportamento, ad esempio per passare come parametro
- Non importa un po 'quale tipo di valori hanno i dati aggregati
In questo caso, è necessario rendere pubblici i campi e saltare i getter / setter. Getter e setter sono comunque goffi e Java è sciocco per non avere proprietà come un linguaggio utile. Poiché il tuo oggetto simile a una struttura non dovrebbe avere alcun metodo, i campi pubblici hanno più senso.
Tuttavia, se uno di questi non si applica, hai a che fare con una vera classe. Ciò significa che tutti i campi dovrebbero essere privati. (Se hai assolutamente bisogno di un campo in un ambito più accessibile, usa un getter / setter.)
Per verificare se la tua struttura presunta ha un comportamento, osserva quando vengono utilizzati i campi. Se sembra violare la parola, non chiedere , allora devi spostare quel comportamento nella tua classe.
Se alcuni dei tuoi dati non dovessero cambiare, devi rendere definitivi tutti quei campi. Potresti considerare di rendere immutabile la tua classe . Se è necessario convalidare i dati, fornire la convalida nei setter e nei costruttori. (Un trucco utile è definire un setter privato e modificare il tuo campo all'interno della tua classe usando solo quel setter.)
Il tuo esempio Bottle probabilmente fallirebbe entrambi i test. Potresti avere un codice (inventato) che assomiglia a questo:
public double calculateVolumeAsCylinder(Bottle bottle) {
return bottle.height * (bottle.diameter / 2.0) * Math.PI);
}
Invece dovrebbe essere
double volume = bottle.calculateVolumeAsCylinder();
Se cambiassi altezza e diametro, sarebbe la stessa bottiglia? Probabilmente no. Quelli dovrebbero essere definitivi. Un valore negativo va bene per il diametro? La tua bottiglia deve essere più alta di quanto sia larga? Il Cap può essere nullo? No? Come lo convalidi? Supponiamo che il cliente sia stupido o malvagio. ( È impossibile dire la differenza. ) È necessario controllare questi valori.
Ecco come potrebbe apparire la tua nuova classe Bottle:
public class Bottle {
private final int height, diameter;
private Cap capType;
public Bottle(final int height, final int diameter, final Cap capType) {
if (diameter < 1) throw new IllegalArgumentException("diameter must be positive");
if (height < diameter) throw new IllegalArgumentException("bottle must be taller than its diameter");
setCapType(capType);
this.height = height;
this.diameter = diameter;
}
public double getVolumeAsCylinder() {
return height * (diameter / 2.0) * Math.PI;
}
public void setCapType(final Cap capType) {
if (capType == null) throw new NullPointerException("capType cannot be null");
this.capType = capType;
}
// potentially more methods...
}