Outra coisa é fazer a consistência, mas deixar a lógica desencapsulada. Em alguns casos, é melhor que o set seja substituído por um método mais conveniente. Vamos ao exemplo clássico. Considerem a seguinte classe, que representa um semáforo (desses de trânsito mesmo):
[code]public class Semaforo {
private Color cor = Color.RED;
public void setCor(Color novaCor) {
if (this.cor == Color.RED && novaCor != Color.GREEN)
throw new IllegalArgumentException(“De vermelho tem que ir para verde!”);
if (this.cor == Color.YELLOW && novaCor != Color.RED)
throw new IllegalArgumentException(“De amarelo tem que ir para vermelho!”);
if (this.cor == Color.GREEN && novaCor != Color.YELLOW)
throw new IllegalArgumentException(“De verde tem que ir para amarelo!”);
this.cor = cor;
}
public void getCor() {
return cor;
}
}[/code]
Notem que aqui existem gets e sets e set faz a validação correta. Não é possível atribuir uma cor inválida. Logo, a classe está encapsulada, certo?
Errado. O atributo está encapsulado, mas a lógica do seu uso não.
Imagine que no seu código você usa a classe semáforo e precisa trocar a cor do semáforo.
if (semaforo.getCor() == Color.YELLOW)
semaforo.setCor(Color.RED);
else if (semaforo.getCor() == Color.GREEN)
semaforo.setCor(Color.YELLOW);
else if (semaforo.getCor() == Color.RED)
semaforo.setCor(Color.GREEN);
O que aconteceu aqui? Esse if faz parte da lógica do semaforo. Mas por nosso set ser “aberto”, a lógica acabou ficando de fora da classe semáforo!!! Se seu semáforo for usado em vários pontos do seu código, esse if vai, certamente, se repetir. Depois de um tempo, se você quiser alterar a ordem do semáforo, ou se uma nova cor surgir, você terá um sério problema. Terá que identificar todos os pontos onde um if desses ocorre e alterar.
O correto seria não fazer um set e encapsular também a lógica do atributo. Veja a nova versão da classe:
[code]
public class Semaforo {
private Color cor = Color.RED;
//Não damos mais a opção de dizer a nova cor.
//O semáforo é quem deve saber isso.
public void trocaCor() {
if (cor == Color.RED)
cor = Color.GREEN;
if (cor == Color.YELLOW)
cor = Color.RED;
if (cor == Color.GREEN)
cor = Color.YELLOW;
//Não era nenhuma dessas? Tem coisa errada. Melhor fazer um assert.
assert(false);
}
public void getCor() {
return cor;
}
}[/code]
O assert é uma boa prática de programação, mas não vem ao caso agora.
O uso desse semáforo vai ser mais confortável e mais seguro. Agora, quem precisar trocar a cor de um semáforo no código só precisa fazer:
semaforo.trocaCor();
As troca sempre estará correta. Também será fácil adicionar novas cores ou mudar a ordem de cores desse semáforo, já que a lógica não ficou exposta.