Método set descarta necessidade de construtor?

Olá!

Estou estudando esta linguagem a pouco tempo e acabei de ler sobre encapsulamento.
Até este momento eu acessava as variáveis de instancia através de “ponto” (ex.: objeto.cor=“azul”; ). Mas descobri que isto é inseguro, pois posso fornecer dados inválidos (ex.: objeto.cor=“galinha”; ).
Para isto, agora utilizo assim: objeto.setColor(“azul”);. Sendo que dentro do setColor método há um código de validação.

Mas, se agora eu utilizo o SET, para que diabos eu preciso do CONSTRUTOR??
A partir de que passei a fazer isto, tive que repetir o código de validação do SET no CONSTRUTOR, para ficar 100% seguro.

Alguém pode me esclarecer esta dúvida? Ainda preciso de CONSTRUTOR? Para o que especificamente

Você pode usar o construtor para:

  1. Forçar a existencia e atribuição de campos obrigatórios;
  2. Criar classes imutáveis (ou seja, que apenas setam valores no construtor, e não tem nenhum set);
  3. Facilitar a criação de objetos (podendo inclusive, criar o objeto e, na mesma linha, coloca-lo numa lista ou como parâmetro de função);
  4. Inicializar valores padrão;

A idéia do construtor é simples:
“Aplicar uma regra de negocio no momento da instanciação do objeto, se neste momento você precisar iniciar atributos com parametros, vc utiliza um construtor que contenha a assinatura que vc necessita”.
Os get/set não substituem os construtores, eles só acessão suas propriedades(atributos) por causa do encapsulamento. gets/sets vem de jabeans, mas o “encapsulamento de atributos” não lhe diz “Olha vc tem q utilizar gets/sets”. pode ser

private Tal atributoTal;
public Tal retornaAtributTal(){
return atributoTal;
}

Falow

O Viny sempre é mais rapido, srsrsrs…
Abs

Entendido Senhores!!!

Agradeço muito pela agilidade na resposta.
Já posso mudar de página no meu livro!

VALEW!!!

E por exemplo, vc poderia ter o seguinte:

public class Carro {
   private String cor; // supondo que a cor seja em string
   //outros atributos
   
   public Carro(String cor) {
      setCor(cor);
   }

   public void setCor(String cor) {
      //define uma logica de validacao....
      this.cor = cor;
   }
}

Isso eliminaria a repetição da validação da sua cor.

Só um detalhe, j0nny.

Existe um erro maligno nessa sua implementação. Você não deve chamar métodos no construtor, a menos que os métodos ou a classe sejam final. Lembre-se que há a possibilidade de sobreposição, e isso implicaria chamar um método de um objeto de uma subclasse que ainda não foi completamente construída.

Eu mesmo já passei por um problema macabro envolvendo esse detalhe de implementação, que me tomou algumas horas de desenvolvimento frustrado.

[quote=ViniGodoy]Só um detalhe, j0nny.

Existe um erro maligno nessa sua implementação. Você não deve chamar métodos no construtor, a menos que os métodos ou a classe sejam final. Lembre-se que há a possibilidade de sobreposição, e isso implicaria chamar um método de um objeto de uma subclasse que ainda não foi completamente construída.

Eu mesmo já passei por um problema macabro envolvendo esse detalhe de implementação, que me tomou algumas horas de desenvolvimento frustrado.[/quote]

Belo detalhe, nunca tinha pensado nisso.
Mas há casos em que a superclasse ainda não esteja ‘pronta’ no momento em que a subclasse está ‘pronta’?

a necessidade de um construtor…

não é sempre que vc ira utilizar um construtor… qnd nao se declara nenhum construtor na classe, o jva cria pra vc… e ai qnd vc especificar deixa-se de utilizar o default…

como ja foi dito…da possibilidade ou obrigação do usuario que ira manipular a classe passar como parametro os valores declarados…

use a cabeça java diz:
o recurso-chave do construtor é que ele é executado antes de o objeto poder ser atribuido a uma referencia. Isso significa que voce poderá interferir e fazer o que for preciso para deixar o objeto pronto para uso […] um construtor lhe permitira entrar no meio da etapa de criação do objeto - dentro da execução… (pagina 178 - construtores) :smiley:

lembrando que construtores não sao considerados métodos…
e tbm ñ se deva chamar metodos nos construtores…

[quote=j0nny]Belo detalhe, nunca tinha pensado nisso.
Mas há casos em que a superclasse ainda não esteja ‘pronta’ no momento em que a subclasse está ‘pronta’?[/quote]

Sim, isso sempre ocorre. A construção ocorre da super em direção as subclasses.

O java até tenta contornar os problemas, o que gera comportamentos estranhos. Por exemplo, se o método sobrescrito usa um atributo da subclasse, esse atributo não vai estar inicializado. Aí o java o inicializa imediatamente. Quando ele chega no construtor da subclasse, esse atributo é inicializado novamente. Se for um atributo simples, como um tipo primitivo, isso tem poucas chances de dar problema. Agora, um objeto pode ser criado duas vezes, e a referência anterior ser excluída. E isso pode gerar problemas.

Um caso típico é quando alguém tem a brilhante idéia (como eu tive e um rapaz num tópico que ajudei há muito tempo também) de, por exemplo, delegar para a subclasse a construção de um painel num JFrame. Aí ele faz algo assim:

public MeuJFrame() { initialize(); add(painelFilho()); }

E o método painelFilho é criado na subclasse. Nesse caso, o que ocorre é que esse add vai adicionar um painel, e quando o construtor do filho rodar ele vai ser recriado, deixando o filho com a referência para outro painel. Note que o painel que está sendo exibido na tela, não é o mesmo que estará no atributo do filho. E como resultado, você terá aquela deliciosa sensação de que todos os seus sets não funcionam nos componentes desse painel.

[quote=ViniGodoy][quote=j0nny]Belo detalhe, nunca tinha pensado nisso.
Mas há casos em que a superclasse ainda não esteja ‘pronta’ no momento em que a subclasse está ‘pronta’?[/quote]

Sim, isso sempre ocorre. A construção ocorre da super em direção as subclasses.

O java até tenta contornar os problemas, o que gera comportamentos estranhos. Por exemplo, se o método sobrescrito usa um atributo da subclasse, esse atributo não vai estar inicializado. Aí o java o inicializa imediatamente. Quando ele chega no construtor da subclasse, esse atributo é inicializado novamente. Se for um atributo simples, como um tipo primitivo, isso tem poucas chances de dar problema. Agora, um objeto pode ser criado duas vezes, e a referência anterior ser excluída. E isso pode gerar problemas.

Um caso típico é quando alguém tem a brilhante idéia (como eu tive e um rapaz num tópico que ajudei há muito tempo também) de, por exemplo, delegar para a subclasse a construção de um painel num JFrame. Aí ele faz algo assim:

public MeuJFrame() { initialize(); add(painelFilho()); }

E o método painelFilho é criado na subclasse. Nesse caso, o que ocorre é que esse add vai adicionar um painel, e quando o construtor do filho rodar ele vai ser recriado, deixando o filho com a referência para outro painel. Note que o painel que está sendo exibido na tela, não é o mesmo que estará no atributo do filho. E como resultado, você terá aquela deliciosa sensação de que todos os seus sets não funcionam nos componentes desse painel.

[/quote]

Interessante, então basicamente a regra é não chamar métodos set no construtor, certo?

A regra é: Só chame métodos no construtor se forem private ou final.