Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Construtor

Qual a vantagem e a desvantagem de inicializar os atributos no construtor? Qual a prática usual? E, no caso da aula, por qual motivo a lista de Aulas não estava dentro do construtor?

4 respostas

Olá.

Não consigo acessar a aula pra ver a lógica da lista não estar no construtor, mas vou tentar te passar a ideia dos construtores com atributos.

Quando uma classe precisa de alguma propriedade preenchida pra funcionar, o ideal é que essa propriedade seja solicitada no construtor. Dessa forma, você evita que um objeto dessa classe seja instanciado sem essa propriedade, obrigando quem utilizar a passar o parâmetro. Você também pode receber valores no construtor para setar atributos privados (private) e utilizá-los nos seus métodos. Um atributo private não conseguirá ser alterado de fora do escopo da classe (salvo exceções), forçando quem estiver utilizando essa classe a criar outro objeto passando um novo valor no construtor pra ter esse novo valor, sem ter alterado o objeto antigo.

Trabalhando com injeção de dependência, por exemplo, você relaciona suas interfaces com as classes que as implementam em um único arquivo, passando os construtores necessários e apenas utilizando as interfaces no restante do código. Precisou mudar o construtor? Só mudar lá na injeção de dependência que vai refletir no resto.

Enfim, espero ter dado uma ideia dos motivos de você querer utilizar construtores com atributos. É bem pela ideia de ter certeza que você terá o essencial pra trabalhar com um objeto dessa classe. Pedindo no construtor obriga quem instancia a classe a passar o parâmetro, logo reduz chance de erro (não pedir no construtor e a pessoa não setar) e garante o valor no parâmetro.

Abs.

Bruno, tudo bom?

Muito obrigado pela didática na resposta! Mas ainda tenho algumas dúvidas:

"Dessa forma, você evita que um objeto dessa classe seja instanciado sem essa propriedade, obrigando quem utilizar a passar o parâmetro"

Você poderia dar um exemplo de código?

Entendi que seria algo como: uma classe a1 que teria como um de seus atributos uma outra classe a2. Nesse caso, instânciando esse atributo a2 no construtor da a1, você evitaria que o objeto que referência a1 seja instanciado sem a2.

Faz sentido?

"Quando uma classe precisa de alguma propriedade preenchida pra funcionar, o ideal é que essa propriedade seja solicitada no construtor"

Você poderia dar um exemplo de código?

Seria algo assim? Todo objeto da classe b1 precisa receber como parâmetro "c" e "d", então você inicializa um objeto b1 no construtor para forçar que, caso os parâmetros não sejam passados, a exception já apareça no construtor?

"Você também pode receber valores no construtor para setar atributos privados (private) e utilizá-los nos seus métodos."

Você poderia dar um exemplo de código?

Nesse caso, qual seria a diferença de setar atributos privados na classe, fora do construtor?

Muito obrigado!

solução!

Olá.

Vamos lá.

Você poderia dar um exemplo de código?

Entendi que seria algo como: uma classe a1 que teria como um de seus atributos uma outra classe a2. Nesse caso, instânciando esse atributo a2 no construtor da a1, você evitaria que o objeto que referência a1 seja instanciado sem a2.

Faz sentido?

Olha um exemplo simples de código que cria uma instância de um objeto do tipo Pessoa passando os parâmetros no construtor (exemplo em C#):

public class Program
{
    public static void Main()
    {
        Pessoa p = new Pessoa("Bruno", 28);
        Console.WriteLine(p.EscreveNomeEIdade());
    }
}

public class Pessoa
{
    public Pessoa(string nome, int idade)
    {
        Nome = nome;
        Idade = idade;
    }

    public string Nome { get; set; }

    public int Idade { get; set; }

    public string EscreveNomeEIdade()
    {
        return "Nome: " + Nome + " / Idade: " + Idade;
    }
}

Está vendo que tem um método EscreveNomeEIdade() que retorna uma string com os valores das propriedades? Imagina se eu chamo esse método sem ter preenchido as propriedades? Vamos ver esse exemplo:

public class Program
{
    public static void Main()
    {
        Pessoa p = new Pessoa();
        Console.WriteLine(p.EscreveNomeEIdade());
    }
}

O retorno seria: Nome: / Idade: 0

Isso porque o construtor não obriga a quem instancia essa classe a passar nenhum argumento, logo se a pessoa instanciar um objeto do tipo Pessoa e não setar na mão as propriedades, você corre esse risco. Com a obrigação dos parâmetros no construtor, você não cai nesse problema (o que não impedem de passarem valores errados no construtor, tipo um int ao invés de string, mas aí é outra questão). Caso você tente instanciar um objeto com construtor vazio ou passando parâmetros que não contenha em nenhum dos construtores da classe, seu código não vai nem compilar. Esse é um exemplo muito básico, mas dá pra ter uma ideia.

Nesse caso, qual seria a diferença de setar atributos privados na classe, fora do construtor?

Nos baseando naquele exemplo de classe pessoa, olha esse código:

public class Program
{
    public static void Main()
    {
        Pessoa p = new Pessoa("Bruno", 28);
        Console.WriteLine(p.EscreveNomeEIdade());
        p.Nome = "André";
        Console.WriteLine(p.EscreveNomeEIdade());
    }
}

Olha a resposta:

Nome: Bruno / Idade: 28
Nome: André / Idade: 28

Agora, vou mudar as propriedades:

public class Pessoa
{
    public Pessoa(string nome, int idade)
    {
        Nome = nome;
        Idade = idade;
    }

    private string Nome { get; set; }

    private int Idade { get; set; }

    public string EscreveNomeEIdade()
    {
        return "Nome: " + Nome + " / Idade: " + Idade;
    }
}

Agora com as propriedades privadas dentro da classe, só ela mesmo pode mudar o valor, logo essa linha aqui não compila mais: p.Nome = "André";

O compilador diz que essa propriedade está inacessível por conta do nível de proteção da propriedade. Desta forma, você não permite que tais propriedades sejam alteradas depois de configuradas. Se quiser outro nome, tem que criar outra Pessoa (outra instância dessa classe).

Pensa que você pode desenvolver uma biblioteca (library) de classes com várias propriedades e métodos, e quem vai usar vai ser outro desenvolvedor. Você define bem suas classes e construtores pra garantir que quem estiver utilizando não faça algo indevido.

Olha outro exemplo de utilização de construtor com parâmetro:

public class Program
{
    public static void Main()
    {
        Pessoa p = new Pessoa("Bruno", 28, 2.000m);
        Console.WriteLine(p.EscreveNomeEIdade());
        Console.WriteLine(p.RetornaSalario());
    }
}

public class Pessoa
{
    public Pessoa(string nome, int idade, decimal salario)
    {
        Nome = nome;
        Idade = idade;
        Salario = "R$ " + salario;
    }

    private string Nome { get; set; }

    private int Idade { get; set; }

    private string Salario { get; set; }

    public string EscreveNomeEIdade()
    {
        return "Nome: " + Nome + " / Idade: " + Idade;
    }

    public string RetornaSalario()
    {
        return Salario;
    }
}

Olha o output:

Nome: Bruno / Idade: 28
R$ 2,000

Eu poderia ter colocado esse tratamento de adicionar o "R$" em um método a parte (o que faz mais sentido, inclusive), mas só quis te mostrar que eu posso receber algo de um time e tratar ele dentro do construtor. Posso fazer validações também tipo essa:

public class Pessoa
{
    public Pessoa(string nome, int idade, decimal salario)
    {
        if (idade < 18)
            throw new ArgumentException("Idade não pode ser menor que 18");

        Nome = nome;
        Idade = idade;
        Salario = "R$ " + salario;
    }
}

Bom, aí estão alguns exemplos, espero que tenha passado uma ideia bacana.

Abs.

Muito bom, obrigado!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software