Delegando para outros construtores

Repare que, se a classe Livro também tivesse um construtor sem
argumentos, como a seguir:

public Livro(Autor autor){

this.autor = autor;
this.isbn = "000-00-00000-00-0";

}

public Livro(){

}

O valor de ISBN só seria inicializado quando o construtor com um
Autor fosse chamado. Para resolver isso, você pode encadear a chamada
dos construtores utilizando a palavra reservada this, como a seguir:

public Livro(Autor autor){

this();
this.isbn = "000-00-00000-00-0";

}

public Livro(){

this.isbn = “000-00-00000-00-0”;

}

Boa tarde, galera. Retirei essa parte de um livro. Gostaria de saber se para inicializar o isbn no construtor sem argumentos (como mostrado logo acima) eu preciso colocar um " this();" no construtor com argumento “Autor autor” e porque?. Obrigado desde já!

Esquece o autor, pois na verdade ele não está fazendo nada. Simbora deixar esse exemplo mais interessante.

Primeiro ponto: isbn é um atributo de instância, logo, toda vez que um novo objeto for criado, se não houver atribuição concreta para ele, seu valor será nulo!

Dá uma olhada nessa classe modificada:

public class Livro{
	
	String isbn;
	
	public Livro(Autor autor){
		this();
		this.isbn = "000-00-00000-00-0"; 
	}
	
	public Livro(){

		this.isbn = "111-11-11111-11-1"; 
	}
	
	public String getISBN(){
		return isbn;
	}

}

Veja, se o valor de isbn não fosse atribuido pelos construtores, o valor padrão seria NULL.
Se o livro for crido passando um argumento Autor, o valor do isbn é 00…, mas se ele for criado com o construtor padrão, o isbn é 11111.

Acredito que o argumento no contrutor foi somente para fins didáticos, onde é possíel demonstrar que dependendo do tipo da sua cadeia de construtores, um atributo pode ter um valor específico.

Agora respondendo sua pergunta, o this não é necessário neste caso, pois sua inicialização já está garantida no construtor com argumentos. Da mesma forma que vc pode usar um super pra acessar construtores das superclasses, da mesma forma é possível fazer uma cadeia de responsabilidades por construtores locais por meio do this.

No exemplo acima, se eu der um new Livro(autor); e executar o getISBN(), o resultado será “000…”. Se eu construir de forma padrão: “1111…”. Você garantiu que a variável tenha um valor específico de acordo com a forma de criação do objeto.

Não precisa, mas é um jeito comum de se fazer isso, pois evita que você fique duplicando o código que atribui o isbn padrão (ou outros atributos). Idealmente, o construtor vazio deve gerar um objeto usável, e os demais construtores devem estendê-lo, adicionando novos parâmetros.

Note que, no seu exemplo, não é necessário atribuir o isbn no construtor com autor, pois o construtor padrão (que é chamado pelo com parâmetro) já faz isso. O código poderia ser:

public Livro(){
  this.isbn = “000-00-00000-00-0”;
}

public Livro(Autor autor){
  this(); // chama o construtor vazio, que atribui o isbn
  this.autor = autor;
  // não é preciso atribuir o isbn de novo aqui
}

Abraço.

1 curtida

Mas eu poderia deixar nos dois construtores o isbn recebendo valor?

Até pode, mas seria código redundante (duplicado), pois estaria atribuindo o mesmo valor para o isbn duas vezes, em sequência. Se fossem valores diferentes, faria mais sentido.

@raphaeloneves

Não sei se foi proposital, mas sua classe modificada não funciona, pois você tem 2 construtores idênticos (mesma assinatura). Acredito que você queria deixar um dos dois sem parâmetros, não?

Abraço.

1 curtida

Sim. Um com parâmetro e outro sem.

ooops! Corrigido, valeu!

Note que não estou falando de ter dois ou mais construtores, mas sim de passar o mesmo valor para um atributo da classe. Você pode ter quantos construtores precisar, mas evite duplicar a atribuição de valores se possível. Exemplo:

public class Livro(){
  private Autor autor;
  private String isbn;
  public Livro(){
    this.isbn = "000-00-00000-00-0";
  }

  public Livro(Autor autor){
    this(); // aqui, chamando o construtor vazio, isbn receberá 000-00-00000-00-0
   this.autor = autor; // até aqui ok
    this.isbn = "000-00-00000-00-0"; //  opa, isso NÃO é necessário. Você já chamou o construtor vazio logo acima, o que quer dizer que o isbn já recebeu esse valor
  }
}

Isso só faz sentido se você passar um valor diferente:

public class Livro(){
  private Autor autor;
  private String isbn;
  public Livro(){
    this.isbn = "000-00-00000-00-0";
  }

  public Livro(Autor autor){
    this(); // aqui, chamando o construtor vazio, isbn receberá 000-00-00000-00-0
    this.autor = autor; // até aqui ok
    this.isbn = "111-11-11111-11-1"; //  agora sim faz mais sentido, pois o novo valor é diferente do anterior
  }
}

Nesse caso, faz mais sentido não chamar o construtor vazio:

public class Livro(){
  private Autor autor;
  private String isbn;
  public Livro(){
    this.isbn = "000-00-00000-00-0";
  }

  public Livro(Autor autor){
   this.autor = autor; // até aqui ok
   this.isbn = "111-11-11111-11-1"; // se você vai mudar o isbn, por que chamar o construtor vazio, se ele só faz isso?
  }
}

Abraço.

1 curtida

Poxa! Muito obrigado TerraSkilll ! Ajudou bastante.