Menu
Coddy logo textTech

Clases selladas (Sealed)

Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy. Lección 22 de 70.

A veces querrás detener la cadena de herencia. La palabra clave sealed evita que una clase sea heredada, bloqueando su implementación para que ninguna otra clase pueda extenderla.

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

// Esto causaría un error de compilación:
// public class SuperDog : FinalDog { }

¿Por qué sellarías una clase? La seguridad y la integridad del diseño son razones comunes. Cuando has diseñado cuidadosamente una clase y no quieres que nadie cambie su comportamiento a través de la herencia, sellarla garantiza que tu implementación permanezca intacta.

También puedes sellar métodos individuales en lugar de clases enteras. Esto evita que se sigan sobrescribiendo, permitiendo al mismo tiempo que la propia clase sea heredada:

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

public class Puppy : Dog
{
    // No se puede sobrescribir Speak() - está sellado
    // Pero se pueden agregar nuevos métodos
    public void Whimper()
    {
        Console.WriteLine("Whimper...");
    }
}

Ten en cuenta que sealed en un método debe combinarse con override. Solo puedes sellar un método que ya fuera virtual en una clase principal. Esto te proporciona un control preciso: permite cierta personalización en la jerarquía de herencia y, después, bloquéala en un punto específico.

challenge icon

Desafío

Fácil

Construyamos un sistema de procesamiento de pagos que demuestre cómo usar sealed para proteger implementaciones críticas. Crearás una jerarquía en la que ciertos métodos de pago puedan extenderse, pero los más seguros estén sellados para evitar cualquier modificación.

Crearás cuatro archivos para organizar tu código:

  • PaymentMethod.cs: Define una clase PaymentMethod en el espacio de nombres Payments. Esta clase base tiene una propiedad Name (string) y un constructor que la establece. Incluye un método virtual llamado ProcessPayment(decimal amount) que devuelve "Processing ${amount} via {Name}".
  • CreditCardPayment.cs: Define una clase CreditCardPayment en el espacio de nombres Payments que hereda de PaymentMethod. Añade una propiedad CardNumber (string). El constructor acepta el nombre y el número de tarjeta, y usa base para pasar el nombre. Sobrescribe ProcessPayment con la palabra clave sealed para que ninguna clase derivada posterior pueda cambiar este comportamiento. Debe devolver "Charging ${amount} to card ending in {last 4 digits of CardNumber}".
  • BankTransfer.cs: Define una clase sealed llamada BankTransfer en el espacio de nombres Payments que hereda de PaymentMethod. Toda esta clase está sellada: nadie puede heredar de ella. Añade una propiedad BankName (string). El constructor acepta el nombre y el nombre del banco. Sobrescribe ProcessPayment para devolver "Transferring ${amount} from {BankName}".
  • Program.cs: En tu archivo principal, crea instancias de los tres tipos de pago usando valores de entrada. Almacénalas como referencias de PaymentMethod y llama a ProcessPayment en cada una para demostrar el polimorfismo con implementaciones selladas.

Recibirás cuatro entradas:

  • Número de tarjeta de crédito (16 dígitos)
  • Nombre del banco
  • Importe del pago

Imprime el resultado de procesar un pago mediante cada método:

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

Por ejemplo, si las entradas son 1234567890123456, First National y 150.00, la salida debería ser:

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

Usa "Generic" como nombre para la instancia base de PaymentMethod, "Credit Card" para el pago con tarjeta de crédito y "Bank Transfer" para la transferencia bancaria.

El método sellado en CreditCardPayment garantiza que, si alguien crea una subclase, no podrá cambiar la forma en que se procesan los pagos con tarjeta de crédito. La clase sellada BankTransfer impide cualquier herencia; ¡ambos son patrones de seguridad importantes en los sistemas de pago!

Pruébalo tú mismo

using System;
using Payments;

class Program
{
    public static void Main(string[] args)
    {
        // Leer las entradas
        string cardNumber = Console.ReadLine();
        string bankName = Console.ReadLine();
        decimal amount = Convert.ToDecimal(Console.ReadLine());
        
        // TODO: Crear una instancia base de PaymentMethod con el nombre "Generic"
        // Almacenarla como una referencia de PaymentMethod
        
        // TODO: Crear una instancia de CreditCardPayment con el nombre "Credit Card" y el número de tarjeta
        // Almacenarla como una referencia de PaymentMethod
        
        // TODO: Crear una instancia de BankTransfer con el nombre "Bank Transfer" y el nombre del banco
        // Almacenarla como una referencia de PaymentMethod
        
        // TODO: Llamar a ProcessPayment en cada una e imprimir los resultados
        // Cada resultado debe estar en su propia línea
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C# online