Sealed Classes
Part of the Object Oriented Programming section of Coddy's C# journey — lesson 22 of 70.
Sometimes you want to stop the inheritance chain. The sealed keyword prevents a class from being inherited, locking down its implementation so no other class can extend it.
public sealed class FinalDog : Animal
{
public override void Speak()
{
Console.WriteLine("Woof!");
}
}
// This would cause a compile error:
// public class SuperDog : FinalDog { }Why would you seal a class? Security and design integrity are common reasons. When you've carefully designed a class and don't want anyone changing its behavior through inheritance, sealing it guarantees your implementation stays intact.
You can also seal individual methods rather than entire classes. This stops further overriding while still allowing the class itself to be inherited:
public class Dog : Animal
{
public sealed override void Speak()
{
Console.WriteLine("Woof!");
}
}
public class Puppy : Dog
{
// Cannot override Speak() - it's sealed
// But can add new methods
public void Whimper()
{
Console.WriteLine("Whimper...");
}
}Notice that sealed on a method must be combined with override. You can only seal a method that was already virtual in a parent class. This gives you precise control: allow some customization in the inheritance hierarchy, then lock it down at a specific point.
Challenge
EasyLet's build a payment processing system that demonstrates how to use sealed to lock down critical implementations. You'll create a hierarchy where certain payment methods can be extended, but the most secure ones are sealed to prevent any modifications.
You'll create four files to organize your code:
PaymentMethod.cs: Define aPaymentMethodclass in thePaymentsnamespace. This base class has aNameproperty (string) and a constructor that sets it. Include avirtualmethod calledProcessPayment(decimal amount)that returns"Processing ${amount} via {Name}".CreditCardPayment.cs: Define aCreditCardPaymentclass in thePaymentsnamespace that inherits fromPaymentMethod. Add aCardNumberproperty (string). The constructor accepts name and card number, usingbaseto pass the name. OverrideProcessPaymentwith thesealedkeyword so no further derived classes can change this behavior. It should return"Charging ${amount} to card ending in {last 4 digits of CardNumber}".BankTransfer.cs: Define asealedclass calledBankTransferin thePaymentsnamespace that inherits fromPaymentMethod. This entire class is sealed - no one can inherit from it. Add aBankNameproperty (string). The constructor accepts name and bank name. OverrideProcessPaymentto return"Transferring ${amount} from {BankName}".Program.cs: In your main file, create instances of all three payment types using input values. Store them asPaymentMethodreferences and callProcessPaymenton each to demonstrate polymorphism with sealed implementations.
You will receive four inputs:
- Credit card number (16 digits)
- Bank name
- Payment amount
Print the result of processing a payment through each method:
{base PaymentMethod result}
{CreditCardPayment result}
{BankTransfer result}For example, if the inputs are 1234567890123456, First National, and 150.00, the output should be:
Processing $150.00 via Generic
Charging $150.00 to card ending in 3456
Transferring $150.00 from First NationalUse "Generic" as the name for the base PaymentMethod instance, "Credit Card" for the credit card payment, and "Bank Transfer" for the bank transfer.
The sealed method in CreditCardPayment ensures that if someone creates a subclass, they cannot change how credit card payments are processed. The sealed class BankTransfer prevents any inheritance at all - both are important security patterns in payment systems!
Cheat sheet
The sealed keyword prevents a class from being inherited or a method from being overridden further in the inheritance chain.
Sealing a class:
public sealed class FinalDog : Animal
{
public override void Speak()
{
Console.WriteLine("Woof!");
}
}
// This would cause a compile error:
// public class SuperDog : FinalDog { }Sealed classes are used for security and design integrity, ensuring the implementation cannot be modified through inheritance.
Sealing a method:
public class Dog : Animal
{
public sealed override void Speak()
{
Console.WriteLine("Woof!");
}
}
public class Puppy : Dog
{
// Cannot override Speak() - it's sealed
// But can add new methods
public void Whimper()
{
Console.WriteLine("Whimper...");
}
}The sealed keyword on a method must be combined with override. You can only seal methods that were already virtual in a parent class. This allows customization up to a specific point in the hierarchy, then locks it down.
Try it yourself
using System;
using Payments;
class Program
{
public static void Main(string[] args)
{
// Read inputs
string cardNumber = Console.ReadLine();
string bankName = Console.ReadLine();
decimal amount = Convert.ToDecimal(Console.ReadLine());
// TODO: Create a base PaymentMethod instance with name "Generic"
// Store it as a PaymentMethod reference
// TODO: Create a CreditCardPayment instance with name "Credit Card" and the card number
// Store it as a PaymentMethod reference
// TODO: Create a BankTransfer instance with name "Bank Transfer" and the bank name
// Store it as a PaymentMethod reference
// TODO: Call ProcessPayment on each and print the results
// Each result should be on its own line
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesNamespaces & DirectivesIntro to Classes & ObjectsThe 'this' KeywordMethods and ParametersFields vs PropertiesConstructorsObject InitializersRecap - Simple Calculator4Inheritance
Basic Inheritance (:) SyntaxThe 'base' KeywordVirtual & Override KeywordsSealed ClassesThe 'object' Base ClassRecap - Employee Hierarchy7Advanced Features
Operator OverloadingIndexers (this[])ToString() OverrideExtension MethodsRecap - Custom List2Properties & Static Members
Auto-Implemented PropertiesRead/Write-Only PropertiesStatic Fields & MethodsStatic ClassesExpression-Bodied Members5Polymorphism & Interfaces
Compile vs Runtime PolyInterface vs Abstract ClassMultiple InterfacesExplicit InterfacesUpcasting & DowncastingRecap - Shape Calculator