Menu
Coddy logo textTech

Classes Seladas

Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy — lição 22 de 70.

Às vezes, você deseja interromper a cadeia de herança. A palavra-chave sealed impede que uma classe seja herdada, bloqueando sua implementação para que nenhuma outra classe possa estendê-la.

public sealed class FinalDog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

// Isso causaria um erro de compilação:
// public class SuperDog : FinalDog { }

Por que você selaria uma classe? Segurança e integridade de design são motivos comuns. Quando você projetou cuidadosamente uma classe e não quer que ninguém altere seu comportamento por meio de herança, selá-la garante que sua implementação permaneça intacta.

Você também pode selar métodos individuais em vez de classes inteiras. Isso impede novas sobrescritas, permitindo ainda que a própria classe seja herdada:

public class Dog : Animal
{
    public sealed override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

public class Puppy : Dog
{
    // Não é possível sobrescrever Speak() - está selado
    // Mas pode adicionar novos métodos
    public void Whimper()
    {
        Console.WriteLine("Whimper...");
    }
}

Observe que sealed em um método deve ser combinado com override. Você só pode selar um método que já era virtual em uma classe pai. Isso lhe dá um controle preciso: permita alguma customização na hierarquia de herança e, em seguida, bloqueie-a em um ponto específico.

challenge icon

Desafio

Fácil

Vamos construir um sistema de processamento de pagamentos que demonstra como usar sealed para bloquear implementações críticas. Você criará uma hierarquia onde certos métodos de pagamento podem ser estendidos, mas os mais seguros são selados para evitar quaisquer modificações.

Você criará quatro arquivos para organizar seu código:

  • PaymentMethod.cs: Defina uma classe PaymentMethod no namespace Payments. Esta classe base possui uma propriedade Name (string) e um construtor que a define. Inclua um método virtual chamado ProcessPayment(decimal amount) que retorna "Processing ${amount} via {Name}".
  • CreditCardPayment.cs: Defina uma classe CreditCardPayment no namespace Payments que herda de PaymentMethod. Adicione uma propriedade CardNumber (string). O construtor aceita o nome e o número do cartão, usando base para passar o nome. Sobrescreva ProcessPayment com a palavra-chave sealed para que nenhuma classe derivada adicional possa alterar esse comportamento. Ele deve retornar "Charging ${amount} to card ending in {last 4 digits of CardNumber}".
  • BankTransfer.cs: Defina uma classe sealed chamada BankTransfer no namespace Payments que herda de PaymentMethod. Esta classe inteira é selada - ninguém pode herdar dela. Adicione uma propriedade BankName (string). O construtor aceita o nome e o nome do banco. Sobrescreva ProcessPayment para retornar "Transferring ${amount} from {BankName}".
  • Program.cs: No seu arquivo principal, crie instâncias de todos os três tipos de pagamento usando valores de entrada. Armazene-os como referências de PaymentMethod e chame ProcessPayment em cada um para demonstrar o polimorfismo com implementações seladas.

Você receberá quatro entradas:

  • Número do cartão de crédito (16 dígitos)
  • Nome do banco
  • Valor do pagamento

Imprima o resultado do processamento de um pagamento através de cada método:

{base PaymentMethod result}
{CreditCardPayment result}
{BankTransfer result}

Por exemplo, se as entradas forem 1234567890123456, First National, e 150.00, a saída deve ser:

Processing $150.00 via Generic
Charging $150.00 to card ending in 3456
Transferring $150.00 from First National

Use "Generic" como o nome para a instância base de PaymentMethod, "Credit Card" para o pagamento com cartão de crédito e "Bank Transfer" para a transferência bancária.

O método selado em CreditCardPayment garante que, se alguém criar uma subclasse, não poderá alterar como os pagamentos com cartão de crédito são processados. A classe selada BankTransfer impede qualquer herança - ambos são padrões de segurança importantes em sistemas de pagamento!

Folha de consulta

A palavra-chave sealed impede que uma classe seja herdada ou que um método seja sobrescrito futuramente na cadeia de herança.

Selando uma classe:

public sealed class FinalDog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

// Isso causaria um erro de compilação:
// public class SuperDog : FinalDog { }

Classes seladas são usadas para segurança e integridade de design, garantindo que a implementação não possa ser modificada através de herança.

Selando um método:

public class Dog : Animal
{
    public sealed override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

public class Puppy : Dog
{
    // Não é possível sobrescrever Speak() - ele está selado
    // Mas é possível adicionar novos métodos
    public void Whimper()
    {
        Console.WriteLine("Whimper...");
    }
}

A palavra-chave sealed em um método deve ser combinada com override. Você só pode selar métodos que já eram virtual em uma classe pai. Isso permite a customização até um ponto específico na hierarquia e, então, a bloqueia.

Experimente você mesmo

using System;
using Payments;

class Program
{
    public static void Main(string[] args)
    {
        // Ler as entradas
        string cardNumber = Console.ReadLine();
        string bankName = Console.ReadLine();
        decimal amount = Convert.ToDecimal(Console.ReadLine());
        
        // TODO: Crie uma instância base de PaymentMethod com o nome "Generic"
        // Armazene-a como uma referência de PaymentMethod
        
        // TODO: Crie uma instância de CreditCardPayment com o nome "Credit Card" e o número do cartão
        // Armazene-a como uma referência de PaymentMethod
        
        // TODO: Crie uma instância de BankTransfer com o nome "Bank Transfer" e o nome do banco
        // Armazene-a como uma referência de PaymentMethod
        
        // TODO: Chame ProcessPayment em cada um e imprima os resultados
        // Cada resultado deve estar em sua própria linha
    }
}
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