As estruturas têm seu lugar, mesmo em Java. Você deve usá-los apenas se as duas coisas seguintes forem verdadeiras:
- Você só precisa agregar dados que não têm nenhum comportamento, por exemplo, passar como parâmetro
- Não importa nem um pouco que tipo de valores agregados os dados têm
Se for esse o caso, você deve tornar os campos públicos e pular os getters / setters. Getters e setters são desajeitados de qualquer maneira, e Java é tolo por não ter propriedades como uma linguagem útil. Como seu objeto de estrutura não deve ter nenhum método, os campos públicos fazem mais sentido.
No entanto, se um deles não se aplicar, você estará lidando com uma classe real. Isso significa que todos os campos devem ser privados. (Se você precisar absolutamente de um campo em um escopo mais acessível, use um getter / setter.)
Para verificar se sua suposta estrutura possui comportamento, observe quando os campos são usados. Se isso parece violar o tell, não pergunte , você precisa mudar esse comportamento para a sua classe.
Se alguns dos seus dados não mudarem, será necessário finalizar todos esses campos. Você pode considerar tornar sua classe imutável . Se você precisar validar seus dados, forneça a validação nos configuradores e construtores. (Um truque útil é definir um setter privado e modificar seu campo dentro da sua classe usando apenas esse setter.)
Seu exemplo de garrafa provavelmente falharia nos dois testes. Você poderia ter um código (artificial) parecido com este:
public double calculateVolumeAsCylinder(Bottle bottle) {
return bottle.height * (bottle.diameter / 2.0) * Math.PI);
}
Em vez disso, deve ser
double volume = bottle.calculateVolumeAsCylinder();
Se você alterasse a altura e o diâmetro, seria a mesma garrafa? Provavelmente não. Aqueles devem ser finais. Um valor negativo está ok para o diâmetro? Sua garrafa deve ser mais alta do que larga? O limite pode ser nulo? Não? Como você está validando isso? Suponha que o cliente seja estúpido ou mau. ( É impossível dizer a diferença. ) Você precisa verificar esses valores.
É assim que sua nova classe Bottle pode ser:
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...
}