Menu
Coddy logo textTech

Composição sobre Herança

Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy. Lição 41 de 70.

A herança cria um forte acoplamento entre as classes. Quando um Car herda de Vehicle, qualquer alteração em Vehicle pode quebrar Car. A composição oferece uma alternativa mais flexível: em vez de herdar comportamento, uma classe contém objetos que fornecem esse comportamento.

Considere um personagem de jogo que pode se mover e atacar. Com herança, você poderia criar uma hierarquia complexa. Com composição, você simplesmente fornece ao personagem os componentes de que ele precisa:

public class MovementBehavior
{
    public void Move() => Console.WriteLine("Moving...");
}

public class AttackBehavior
{
    public void Attack() => Console.WriteLine("Attacking!");
}

public class Character
{
    private MovementBehavior movement = new MovementBehavior();
    private AttackBehavior attack = new AttackBehavior();
    
    public void Move() => movement.Move();
    public void Attack() => attack.Attack();
}

A principal diferença está no relacionamento. A herança representa "é um" (um Dog é um Animal), enquanto a composição representa "tem um" (um Character tem um comportamento de movimento). A composição permite trocar comportamentos em tempo de execução, combinar capacidades livremente e evitar o problema da classe base frágil.

Use herança quando houver uma relação hierárquica genuína. Escolha composição quando precisar de flexibilidade, quando os comportamentos puderem ser compartilhados entre classes não relacionadas ou quando quiser alterar o comportamento dinamicamente.

challenge icon

Desafio

Fácil

Vamos criar um sistema de notificações que demonstra o poder da composição em vez da herança. Em vez de criar uma hierarquia complexa de classes de notificação, você vai compor um NotificationSender fornecendo a ele componentes de comportamento intercambiáveis.

Você organizará seu código em três arquivos:

  • Behaviors.cs: crie duas classes de comportamento no namespace Notifications que lidam com diferentes aspectos do envio de notificações:
    • FormattingBehavior - tem um método Format(string message) que retorna a mensagem envolvida por [ALERT] no início e [END] no final
    • DeliveryBehavior - tem um método Deliver(string channel, string message) que retorna uma string no formato Sending via {channel}: {message}
  • NotificationSender.cs: crie uma classe NotificationSender no namespace Notifications que use composição para combinar comportamentos. Seu remetente deve:
    • Conter instâncias de FormattingBehavior e DeliveryBehavior como campos privados
    • Ter uma propriedade Channel (string) que armazene o nome do canal de entrega
    • Ter um construtor que aceite o nome do canal
    • Ter um método Send(string message) que primeiro formate a mensagem usando o comportamento de formatação, depois a entregue usando o comportamento de entrega e retorne o resultado final
  • Program.cs: no seu arquivo principal, crie um NotificationSender com um canal obtido da entrada e, em seguida, envie uma mensagem obtida da entrada. Imprima o resultado para mostrar como os comportamentos compostos funcionam juntos.

Você receberá duas entradas:

  • O nome do canal de entrega (por exemplo, Email, SMS)
  • A mensagem a ser enviada

Imprima o resultado da chamada de Send() no seu remetente de notificações.

Por exemplo, se as entradas forem Email e Server is down, a saída deverá ser:

Sending via Email: [ALERT] Server is down [END]

Observe como o NotificationSender não herda de nada — ele simplesmente "tem" comportamentos de formatação e entrega. Essa abordagem de composição significa que você poderia facilmente substituir qualquer um dos comportamentos sem alterar a classe do remetente ou reutilizar esses comportamentos em classes completamente diferentes!

Experimente você mesmo

using System;
using Notifications;

class Program
{
    public static void Main(string[] args)
    {
        // Ler entrada
        string channel = Console.ReadLine();
        string message = Console.ReadLine();

        // TODO: Criar um NotificationSender com o channel
        
        // TODO: Enviar a message e imprimir o resultado
        
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de C# online