1
resposta

[Projeto] Faça como eu fiz: cadastro de funcionários

Resolução:
Funcionario.cs

namespace PraticandoC_05.CadastroFuncionarios02
{
    internal abstract class Funcionario
    {
        public string? Nome { get; protected set; }
        public string? Cargo { get; protected set; }
    }
}

IResumo.cs

namespace PraticandoC_05.CadastroFuncionarios02
{
    internal interface IResumo  
    {
        string Resumo { get; }
    }
}

Interno.cs

namespace PraticandoC_05.CadastroFuncionarios02
{
    internal class Interno : Funcionario, IResumo
    {
        public Interno(string? nome, string? cargo, decimal salario)
        {
            Nome = nome;
            Cargo = cargo;
            Salario = salario;
        }

        public decimal Salario { get; set; }

        public string Resumo =>
            $"Funcionário(a) {Nome} – Cargo: {Cargo} – Salário: R$ {Salario}\n";

    }
}

Freelancer.cs

namespace PraticandoC_05.CadastroFuncionarios02
{
    internal class Freelancer : Funcionario, IResumo
    {

        public decimal ValorProjeto { get; set; }
        public Freelancer(string? nome, string? cargo, decimal valorProjeto)
        {
            Nome = nome;
            Cargo = cargo;
            ValorProjeto = valorProjeto;
        }

        public string Resumo =>
            $"Funcionário(a) {Nome} – Cargo: {Cargo} – Projeto atual: R$ {ValorProjeto}\n";
    }
}

Program.cs

using PraticandoC_05.CadastroFuncionarios02;

var interno1 = new Interno("Harry", "Desenvolvedor Pleno", 10000.00m);
var freelancer1 = new Interno("Sunny", "Designer Especializado", 7000.00m);

Console.WriteLine(interno1.Resumo);
Console.WriteLine(freelancer1.Resumo);
1 resposta

Olá, Christopher. Como vai?

Parabéns pela resolução do desafio! O seu código demonstra uma excelente compreensão sobre o uso de classes abstratas, herança e interfaces no ecossistema do C# e do ecossistema .NET.

A criação da classe abstrata Funcionario para encapsular as propriedades comuns (Nome e Cargo) com o modificador de acesso protected set ficou perfeita, garantindo que apenas as classes filhas possam definir esses valores no momento da construção. O uso da interface IResumo também foi uma ótima escolha de design, permitindo que diferentes tipos de funcionários implementem a propriedade Resumo de forma personalizada através de Expression-bodied members (=>).

Para agregar ainda mais valor ao seu projeto, identifiquei um pequeno detalhe de digitação no seu arquivo Program.cs que pode gerar confusão no comportamento do seu sistema.

No trecho onde você instancia o freelancer1, você declarou a variável, mas acabou instanciando a classe Interno em vez de Freelancer:

var freelancer1 = new Interno("Sunny", "Designer Especializado", 7000.00m);

Como o construtor usado foi o de Interno, o valor 7000.00m foi atribuído à propriedade Salario (e não ValorProjeto), e a mensagem exibida na tela seguirá o padrão da classe Interno, exibindo a palavra "Salário" em vez de "Projeto atual".

Para corrigir isso e garantir que o polimorfismo funcione exatamente como você planejou, basta alterar a instanciação para a classe correta:

var freelancer1 = new Freelancer("Sunny", "Designer Especializado", 7000.00m);

Uma dica de boa prática: Tipagem por Interface

Aproveitando que você criou a interface IResumo, uma prática muito comum no mercado quando trabalhamos com herança e interfaces é armazenar os objetos criados em uma coleção (como uma List<T>) do tipo da interface. Isso nos permite iterar sobre diferentes tipos de funcionários e exibir o resumo de todos eles de uma só vez, deixando o código do Program.cs ainda mais limpo:

using PraticandoC_05.CadastroFuncionarios02;

var interno1 = new Interno("Harry", "Desenvolvedor Pleno", 10000.00m);
var freelancer1 = new Freelancer("Sunny", "Designer Especializado", 7000.00m);

// Criando uma lista que aceita qualquer classe que implemente IResumo
List<IResumo> listaFuncionarios = new List<IResumo> { interno1, freelancer1 };

// Percorrendo a lista e exibindo os resumos dinamicamente
foreach (var funcionario in listaFuncionarios)
{
    Console.WriteLine(funcionario.Resumo);
}

Dessa forma, se no futuro você criar novas classes como Terceirizado ou Estagiario, desde que elas implementem IResumo, o seu loop foreach continuará funcionando perfeitamente sem precisar de nenhuma alteração!

Continue com o ótimo trabalho e foco nos conceitos de Orientação a Objetos!

Espero que possa ter lhe ajudado!