class sealing
object-oriented programming
encapsulation
software design
programming best practices

When and why would you seal a class?

Object-Oriented Design practice on Codemia

Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.

Practice OOD

Introduction

Sealing a class means preventing further inheritance from that class. It is a design choice used to protect invariants, simplify maintenance, and communicate intended extension points clearly. The right decision depends on API stability goals, correctness constraints, and framework behavior.

What Sealing Means in Practice

In languages such as C sharp, a sealed class cannot be inherited.

csharp
1public sealed class TokenValidator
2{
3    public bool IsValid(string token)
4    {
5        return !string.IsNullOrWhiteSpace(token);
6    }
7}

This enforces that behavior is fixed at this level.

In modern Java, sealed can allow only specific subclasses, which is a related but different model.

Why Seal a Class

Common reasons:

  1. Protect critical invariants.
  2. Prevent unsafe overrides.
  3. Simplify reasoning about behavior.
  4. Improve API clarity for consumers.

If subclassing can break guarantees, sealing is often the safest default.

Seal Classes with Security-Sensitive Logic

Classes handling authentication, crypto, or permission checks often benefit from sealing. Preventing override reduces risk of altered behavior through inheritance.

Example concept:

  • Validation class should not allow subclass to bypass checks.
  • Sealing ensures one audited implementation path.

This is not full security control by itself, but it reduces accidental extension risks.

Seal for Stable Value Objects

Immutable value objects often do not need subclassing. Sealing keeps equality and hash behavior predictable.

csharp
1public sealed class Money
2{
3    public decimal Amount { get; }
4    public string Currency { get; }
5
6    public Money(decimal amount, string currency)
7    {
8        Amount = amount;
9        Currency = currency;
10    }
11}

Predictable value semantics are easier when inheritance is blocked.

Performance and Runtime Considerations

In some runtimes, sealed classes can enable modest optimization opportunities because virtual dispatch paths are simpler. This should be treated as secondary benefit, not primary reason.

Design clarity and correctness are usually stronger justifications than micro-performance expectations.

When Not to Seal

Do not seal by default if class is intended as extension point for framework users or plugins. Sealing in that case can force brittle workarounds and reduce API usefulness.

Before sealing, ask:

  • Should users customize behavior through inheritance.
  • Is composition a better extension mechanism.
  • Will this restriction break expected framework patterns.

A class can stay unsealed while still controlling extensibility with protected members and documented contracts.

Prefer Composition for Controlled Extensibility

Many teams seal concrete classes and expose interfaces for extension.

csharp
1public interface IPriceCalculator
2{
3    decimal Calculate(decimal basePrice);
4}
5
6public sealed class DefaultPriceCalculator : IPriceCalculator
7{
8    public decimal Calculate(decimal basePrice) => basePrice;
9}

Consumers can provide alternate implementations without subclassing your concrete type.

Versioning and API Evolution

Sealing affects consumers. If class was inheritable and you seal it later, that is a breaking change for users who subclassed it.

For public libraries, decide sealing strategy early and document it. Stable extension contracts reduce upgrade friction.

Testing Implications

Sealed classes can limit mocking strategies that rely on subclass proxies in some test frameworks. If this matters, design around interfaces and dependency injection.

This keeps production behavior constrained while preserving testability.

Practical Decision Checklist

Seal a class when most answers are yes:

  1. Behavior must remain invariant.
  2. Inheritance adds risk without clear value.
  3. Public extension point is not intended.
  4. Composition via interface covers customization needs.

Using a checklist prevents ad hoc inconsistent design decisions.

Common Pitfalls

  • Sealing everything without considering extension requirements.
  • Leaving critical behavior unsealed where overrides can break invariants.
  • Treating sealing as security guarantee on its own.
  • Changing public class from unsealed to sealed in minor release.
  • Ignoring testability impact when no interface abstraction exists.

Summary

  • Sealing prevents inheritance and can protect class invariants.
  • It is useful for stable, security-sensitive, or immutable behavior.
  • Do not seal classes meant to be framework extension points.
  • Prefer interface-based composition for controlled customization.
  • Decide and document sealing policy early for API stability.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Object-Oriented Design practice on Codemia

Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.

Practice OOD

All Rights Reserved.