Uso de setters no construtor – java orientação-a-objetos construtor

Pergunta:


Eu gostaria de saber se há alguma diferença, semanticamente falando, entre esses dois construtores:

public Aluno(String n, float n1, float n2) {
   this.nome = n;
   this.setNota1(n1);
   this.setNota2(n2);
}

e

public Aluno(String n, float n1, float n2) {
   this.nome = n;
   this.nota = n1;
   this.nota2 = n2;
}

Autor da pergunta Matheus Link

Resposta Guilherme Nascimento:

Com isto:

this.nota = n1;
this.nota2 = n2;

Você esta acessando as variaveis diretamente. Já estes dois são métodos que podem fazer qualquer coisa:

this.setNota1(n1);
this.setNota2(n2);

No caso se setNota1 for assim:

public setNota1(float n1) {
   this.nota = n1;
}

Então acho que é redundante criar um método apenas pra setar uma variavel, melhor ficar com o primeiro mesmo:

public Aluno(String n, float n1, float n2) {
   this.nome = n;
   this.nota = n1;
   this.nota2 = n2;
}

No caso você só vai usar o setNota1 e setNota2 quando quiser alterar apenas as notas, isto eu quero dizer fora do método, assim:

Foo test = new Aluno("João", 6, 6.5);

//Aqui se a condição for true ele irá mudar apenas a nota1:
if (minha condição) {
    test.setNota1(8);
}

Recomendo que leia:

Não sei exatamente o que você quis dizer com semântica, mas podemos ver a questão de várias perspectivas.

Clareza

Usar métodos setter pode ser mais confuso pois se outra pessoa vai ler o seu código.

Ela pode assumir incorretamente que o método setter executa ou não alguma lógica dentro dele, então ela precisa navegar para os métodos e olhar o que eles fazem.

Observe nas outras respostas que elas sempre acabam inferindo algo ou colocando uma condição. Imagine um sistema com vários casos desse e você pode extrapolar quanta complexidade isso vai adicionar à vida de todos.

Sempre use a solução mais simples. Neste caso, sempre use a atribuição direta quando possível.

Eu imagino que isso pode parecer “feio” para alguns, principalmente porque quando começamos a usar orientação a objetos, ficamos com a impressão que qualquer manipulação direta de atributos de alguma forma quebra o encapsulamento.

Mas o escopo da classe é de propriedade dela mesma. Uma classe não precisa de segredos para si mesma, ou começamos a enveredar para a insanidade. Poderíamos dizer que uma classe que encapsula a si mesma tem múltiplas personalidades?

Efeito

Imaginando agora que os setters apenas atribuem, o efeito final seria o mesmo da atribuição. Porém, isso não é sempre tão simples, principalmente onde há concorrência envolvida.

Entenda concorrência como o ato de acessar e modificar um mesmo atributo ou objeto a partir de diferentes threads ao mesmo tempo.

Em cenários concorrentes, você sempre deve usar os modificadores final ou volatile, pois eles garantem que o estado das variáveis vai ser escrito na memória principal e todas as threads vão enxergar o valor correto. Caso contrário uma thread pode ler o valor antigo em cache.

Uma forma eficiente de compartilhar objetos entre threads é usando objetos imutáveis. Nesse caso, é recomendável usar final em todos os atributos. Exemplo:

private final String nome;
private final float n1;

No exemplo acima, os atributos final somente podem ser atribuídos uma única vez e isso deve ocorrer até o fim da execução do construtor. Atributos final não podem ter a atribuição delegada a um setter.

Manutenção e evitando erros bobos

Além de atributos, podemos também declarar os parâmetros como final, isto é, que não podem ter o valor alterado. Exemplo:

public Aluno(final String n, final float n1, final float n2) {...}

No que isso ajuda?

Primeiro, você evita erros bobos como:

public Aluno(String nome, float nota1, float nota2) {
   this.nome = nome;
   this.nota1 = nota1;
   nota2 = nota2;
}

Acredite, já corrigi errinhos bobos como este acima em produção muitas vezes. Isso seria evitado se os parâmetros fosse final:

public Aluno(final String nome, final float nota1, final float nota2) {
   this.nome = nome;
   this.nota1 = nota1;
   nota2 = nota2; //erro de compilação aqui
}

Isso também ajuda a lembrar que não se deve modificar parâmetros de métodos para reusá-lo como uma variável, como se isso fosse economizar memória ou algo do tipo.

Executando lógica

Se existe a necessidade de executar alguma lógica no método setter, sugiro uma alternativa:

public Aluno(String nome, float nota1, float nota2) {
   this.nome = nome;
   this.nota1 = verificarNotaValida(nota1);
   this.nota2 = verificarNotaValida(nota2);
}

public void setNota1(float nota1) {
    this.nota1 = verificarNotaValida(nota1);
}

Extrair a lógica de validação permite maior reúso e deixa o código claro.

Depende do que os métodos setNota1() e setNota2() fazem. Se eles só atribuem o valor do parâmetro para nota e nota2, então não há diferença alguma. Obviamente que se os métodos fazem qualquer coisa diferente, mínima que seja, então há diferença.

Não porque os atributos são todos da mesma classe. A não ser que os métodos set façam mais alguma coisa além de atribuir valor ao atributo.

Fonte

Related Posts:

Qual a diferença entre AppCompatActivity e Activity? – android android-activity
Pergunta: Qual a diferença da AppCompatActivity para Activity ? A partir de qual versão a AppCompatActivity foi adicionada ao Android? Autor da pergunta Luhhh A diferença reside ...
Como abreviar palavras em PHP? – php string
Pergunta: Possuo informações comuns como nome de pessoas e endereços, e preciso que elas contenham no máximo 30 caracteres sem cortar palavras. Exemplo: 'Avenida Natalino João Brescansin' ...
Qual é a finalidade de um parêntese vazio numa declaração Lambda? – c# expressões-lambda característica-linguagem
Pergunta: Criei um exemplo de uma declaração Lambda sem argumentos, entretanto, estou com duvidas referente a omissão do parêntese vazio () na declaração. Veja o exemplo: class ...
Boas práticas para URI em API RESTful – api rest restful
Pergunta: Estou com dúvida em relação às URIs de alguns recursos da api que estou desenvolvendo. Tenho os recursos projetos e atividades com relação 1-N, ...
Dúvidas sobre a integração do MySQL com Java – java mysql netbeans
Pergunta: Estou criando um sistema no NetBeans, utilizando a linguagem Java e o banco de dados MySQL. Escrevi o seguinte código para realizar a conexão ...
Qual é a finalidade da pasta Model do framework Inphinit? – php inphinit
Pergunta: No Inphinit micro-framework existe a pasta Model que fica dentro da pasta application, e nela é onde ficam as classes, mas eu estou muito ...
Uso do ‘@’ em variáveis – javascript typescript coffeescript
Pergunta: Vejo em algumas linguagens que compilam para javascript, como TypeScript e CoffeeScript, o uso do @ em variáveis, como também, casos em que o ...
Qual tamanho máximo um arquivo JSON pode ter? – json arquivo
Pergunta: Vou dar um exemplo para conseguir explicar minha duvida: Preciso recuperar informação de imagens vindas de uma API, esse banco de imagens me retorna JSON's ...
O que é Teste de Regressão? – terminologia engenharia-de-software testes
Pergunta: Na matéria de Teste de Software o professor abordou um termo chamado Teste de Regressão, isto dentro da disciplina de teste de software. Sendo ...
O que é um construtor da linguagem? – php característica-linguagem
Pergunta: Em PHP, já li e ouvi várias vezes a respeito dos Construtores da Linguagem. Os casos que sempre ouvi falar deles foi em casos ...
Função intrínseca para converter numérico para string – cobol
Pergunta: Estou a tentar saber se existe alguma função intrínseca do COBOL para converter um data numérico para string sem precisar usar a cláusula REDEFINES: ( ...
Porque usar implements? – java android
Pergunta: Qual a diferença entre usar btn.setOnClickListener(new OnClickListener() { e public class MainActivity extends Activity implements OnClickListener{ Estive fazendo um curso de Android e meu professor falou que ...
O que é XHTML e quando deve ser usado? – html xml xhtml
Pergunta: O que eu sei é que o XHTML precisa ser XML válido. Isso implica, por exemplo, que todas as tags precisam ser fechadas. Por ...
Uma placa aceleradora de vídeo pode melhorar o desempenho não-gráfico? [fechada] – desempenho
Pergunta: Para desenvolver em Ruby on Rails, eu utilizo aqui uma máquina virtual do VirtualBox com Ubuntu Server 14.04 sem interface gráfica instalada. Recentemente descobri uma ...
Concat() VS Union() – c# .net
Pergunta: Qual a diferença entre Concat() e Union() ? Quando usar Concat() e quando usar Union() ? Somente pode ser usado em list ? ...

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *