Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

Solucionado
(ver solução)
1
resposta

[Projeto] Faça como eu fiz: ações em botões de interface gráfica

Classe Program:

List<IAcaoBotao> acoes = new()
{
    new SalvarAcao(),
    new EditarAcao(),
    new ExcluirAcao()
};

foreach (var acao in acoes)
{
    acao.Executar();
}

Interface IAcaoBotao:

namespace Polimorfismo.BotoesInterfaceGrafica;

internal interface IAcaoBotao
{
    public void Executar();
}

Classe SalvarAcao:

namespace Polimorfismo.BotoesInterfaceGrafica;

internal class SalvarAcao : IAcaoBotao
{
    public void Executar()
    {
        Console.WriteLine("Salvando dados no banco...");
    }
}

Classe EditarAcao:

namespace Polimorfismo.BotoesInterfaceGrafica;

internal class EditarAcao : IAcaoBotao
{
    public void Executar()
    {
        Console.WriteLine("Editando informações do cadastro...");
    }
}

Classe ExcluirAcao:

namespace Polimorfismo.BotoesInterfaceGrafica;

internal class ExcluirAcao : IAcaoBotao
{
    public void Executar()
    {
        Console.WriteLine("Excluindo registro do sistema...");
    }
}
1 resposta
solução!

Olá, Fabiano. Como vai?

Excelente implementação! O seu código demonstra de forma muito limpa e prática o verdadeiro poder do Polimorfismo de Subtipos e o uso de interfaces no C#.

Ao criar a interface IAcaoBotao, você estabeleceu um contrato que garante que qualquer classe que a implemente possua o método Executar(). Isso permitiu que, na classe Program, você tratasse objetos de tipos totalmente diferentes (SalvarAcao, EditarAcao, ExcluirAcao) como se fossem do mesmo tipo genérico dentro da lista List<IAcaoBotao>.


Vantagens da sua Abordagem (Clean Code e Extensibilidade)

O grande trunfo da sua estrutura é o respeito ao princípio do Open/Closed Principle (Princípio do Aberto/Fechado). Se amanhã o sistema precisar de um novo botão, como "ImprimirRelatorioAcao", você não precisará alterar a estrutura do seu loop principal ou colocar blocos cheios de if/else ou switch/case.

Bastará criar a nova classe implementando a interface:

internal class ImprimirAcao : IAcaoBotao
{
    public void Executar()
    {
        Console.WriteLine("Enviando documento para a impressora...");
    }
}

E depois, apenas adicioná-la na sua lista na classe Program. O loop foreach continuará funcionando perfeitamente sem saber os detalhes internos de como a impressão é feita.


Uma Pequena Dica de Sintaxe sobre Interfaces em C#

O seu código está perfeito e roda sem problemas nas versões modernas do C#. Apenas como curiosidade técnica de boas práticas, ao declarar métodos dentro de uma interface:

internal interface IAcaoBotao
{
    public void Executar();
}

Historicamente, os métodos de uma interface em C# são implicitamente públicos. Por isso, a maior parte da comunidade e dos guias de estilo costuma omitir o modificador public na assinatura do método dentro da interface, deixando apenas assim:

internal interface IAcaoBotao
{
    void Executar(); // Implicitamente público
}

(Nas classes que implementam a interface, como SalvarAcao, o uso do public continua sendo obrigatório).

Parabéns pelo projeto e pela organização dos namespaces. O entendimento desse conceito é um divisor de águas para criar arquiteturas de sistemas robustas, como padrões de projeto (Design Patterns) como o Command ou Strategy.

Espero que possa ter lhe ajudado!