Las estructuras tienen su lugar, incluso en Java. Solo debe usarlos si las siguientes dos cosas son ciertas:
- Solo necesita agregar datos que no tengan ningún comportamiento, por ejemplo, pasar como parámetro
- No importa un poco qué tipo de valores tienen los datos agregados
Si este es el caso, debe hacer públicos los campos y omitir los captadores / establecedores. Getters y setters son torpes de todos modos, y Java es tonto por no tener propiedades como un lenguaje útil. Dado que su objeto tipo estructura no debería tener ningún método de todos modos, los campos públicos tienen más sentido.
Sin embargo, si alguno de esos no se aplica, se trata de una clase real. Eso significa que todos los campos deben ser privados. (Si realmente necesita un campo en un alcance más accesible, use un captador / definidor).
Para verificar si su supuesta estructura tiene comportamiento, observe cuándo se usan los campos. Si parece violar la información , no preguntes , entonces debes mover ese comportamiento a tu clase.
Si algunos de sus datos no cambian, entonces debe hacer que todos esos campos sean finales. Puede considerar hacer que su clase sea inmutable . Si necesita validar sus datos, proporcione la validación en los instaladores y constructores. (Un truco útil es definir un setter privado y modificar su campo dentro de su clase usando solo ese setter).
Su ejemplo de botella probablemente fallaría en ambas pruebas. Podría tener un código (artificial) que se vea así:
public double calculateVolumeAsCylinder(Bottle bottle) {
return bottle.height * (bottle.diameter / 2.0) * Math.PI);
}
En cambio debería ser
double volume = bottle.calculateVolumeAsCylinder();
Si cambiara la altura y el diámetro, ¿sería la misma botella? Probablemente no. Esos deberían ser finales. ¿Está bien un valor negativo para el diámetro? ¿Debe su botella ser más alta que ancha? ¿Puede la gorra ser nula? ¿No? ¿Cómo estás validando esto? Suponga que el cliente es estúpido o malvado. ( Es imposible notar la diferencia ) . Debe verificar estos valores.
Así es como podría verse su nueva clase de botella:
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...
}