Use of setters in the constructor

4

I would like to know if there are any semantically speaking differences between these two constructors:

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

and

public Aluno(String n, float n1, float n2) {
   this.nome = n;
   this.nota = n1;
   this.nota2 = n2;
}
    
asked by anonymous 02.11.2015 / 03:20

4 answers

2

With this:

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

You are accessing the variables directly. Already these two are methods that can do anything:

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

In case if setNota1 is like this:

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

So I think it's redundant to create a method just to set a variable, better stick with the same one:

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

In case you are only going to use setNota1 and setNota2 when you want to only change the notes, this I mean out of method, like this:

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);
}

I recommend you read:

02.11.2015 / 03:30
5

I do not know exactly what you meant by semantics , but we can see the issue from various perspectives.

Clarity

Using setter methods can be more confusing because someone else will read your code.

It may incorrectly assume that the setter method performs some logic within it, so it needs to navigate to the methods and look at what they do.

Notice in the other answers that they always end up inferring something or putting a condition. Imagine a system with multiple cases of this and you can extrapolate how much complexity this will add to everyone's life.

Always use the simplest solution. In this case, always use direct assignment when possible.

I imagine this may seem "ugly" to some, especially since when we first start using object orientation, we get the impression that any direct manipulation of attributes somehow breaks the encapsulation.

But the class scope is owned by itself. A class does not need secrets for itself, or we begin to embark on insanity. Could we say that a class that encapsulates itself has multiple personalities?

Effect

Imagining now that the setters only assign, the final effect would be the same as the assignment. However, this is not always so simple, especially where there is competition involved.

Understand competition as the act of accessing and modifying a single attribute or object from different threads at the same time.

In concurrent scenarios, you should always use the final or volatile modifiers, as they ensure that the state of the variables will be written to main memory and all threads will see the value right. Otherwise a thread can read the old value cached.

An efficient way to share objects between threads is by using immutable objects. In this case, it is recommended that you use final on all attributes. Example:

private final String nome;
private final float n1;

In the example above, the final attributes can only be assigned once and this must occur until the builder runs. Attributes final can not have delegated assignment to a setter .

Maintenance and avoiding silly errors

In addition to attributes, we can also declare the parameters as final , that is, they can not have the value changed. Example:

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

What does this help?

First, you avoid silly errors like:

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

Believe me, I have already corrected silly mistakes like this one up in production many times. This would be avoided if the parameters were 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
}

This also helps to remember that you should not modify method parameters to reuse it as a variable, as if this would save memory or something.

Running logic

If there is a need to run some logic in the setter method, I suggest an alternative:

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);
}

Extracting the validation logic allows more reuse and leaves the code clear.

    
02.11.2015 / 04:12
2

Depends on what methods setNota1() and setNota2() do. If they only assign the parameter value to nota and nota2 , then there is no difference whatsoever. Obviously if the methods do anything different, however minimal, then there's a difference.

    
02.11.2015 / 03:28
1

Not because the attributes are all of the same class. Unless the set methods do more than assign value to the attribute.

    
02.11.2015 / 03:29