In object-oriented programming (OOP), a sealed modifier is a mechanism that’s used to restrict the inheritance and prevent methods, members, and properties from being overridden.
The implementation of a sealed modifier is different across different languages, but the purpose is the same: to prevent the overriding of class methods and members and inheritance of classes. This Answer will cover how the concept of sealed modifiers is used in different programming languages.
In C#, we can use the sealed
keyword to prevent further inheritance or overriding.
A class marked as sealed
can’t be inherited by other classes.
A method marked as sealed
can’t be overridden in derived classes.
A property can also be sealed to prevent further modification in derived classes.
Here, the DerivedClass
attempts to inherit from the BaseClass
that is sealed, and as a result, a compilation error will occur.
using System;sealed class BaseClass{public void DisplayMessage(){Console.WriteLine("This is a sealed class.");}}class DerivedClass : BaseClass // This will result in a compilation error{}class Program{static void Main(string[] args){BaseClass sealedObj = new BaseClass();sealedObj.DisplayMessage();// Attempting to inherit from BaseClass results in a compilation error// DerivedClass derivedObj = new DerivedClass();}}
To avoid the error in the code above, try to run it without inheriting the BaseClass
class.
We can also apply the sealed
keyword with a method that’s trying to override a virtual method of the base class. This case will allow the inheritance, but it will prevent the virtual method of the base class from being overridden.
Note: The
sealed
keyword can’t be used with abstract classes as an abstract class should be inherited and its functions or methods should be implemented in the child class.
In the below example, DerivedClass
can be inherited, but its DisplayMessage
method cannot be overridden further. The sealed
keyword prevents a method from being overridden further in derived classes.
using System;class BaseClass{public virtual void DisplayMessage(){Console.WriteLine("This is the base class.");}}class DerivedClass : BaseClass{public sealed override void DisplayMessage(){Console.WriteLine("This is the derived class.");}}class FurtherDerivedClass : DerivedClass{// This will result in a compilation error if we try to override DisplayMessage again// public override void DisplayMessage()// {// Console.WriteLine("Further derived class.");// }}class Program{static void Main(string[] args){DerivedClass derivedObj = new DerivedClass();derivedObj.DisplayMessage();}}
In Java, the final
keyword is used to achieve similar behavior.
A final
class can’t be subclassed.
A final
method can’t be overridden by subclasses.
A variable (field) marked as final
can’t be modified after it has been initialized.
Here, the final
keyword will prevent the inheritance of the base class. Let’s run the following code. It’ll throw an error.
final class BaseClass {void Print() {System.out.println("This is a Base class.");}}// This will result in a compilation error, as BaseClass is marked finalclass DerivedClass extends BaseClass {}public class Main {public static void main(String[] args) {BaseClass sealedObj = new BaseClass();sealedObj.Print();}}
In the below example, BaseClass
can be inherited, but its printMessage
method cannot be overridden. The final
keyword prevents a method from being overridden in derived classes.
class BaseClass {public final void printMessage() {System.out.println("This is a final method.");}}class DerivedClass extends BaseClass {// This will result in a compilation error if we try to override printMessage// @Override// public void printMessage() {// System.out.println("Trying to override a final method.");// }}class Main {public static void main(String[] args) {DerivedClass derivedObj = new DerivedClass();derivedObj.printMessage();}}
In C++, there is no keyword or concept that is equivalent to sealed
modifiers.
However, in C++, to stop the class from being inherited, we can make the constructors’ and destructors’ scope private or protected.
The final
keyword can be used to prevent the method to be overridden.
Here we use the final
keyword to prevent method overriding. The code will throw an error.
#include <iostream>class BaseClass {public:void Print() {std::cout << "This is a base class method." << std::endl;}};class DerivedClass : public BaseClass {public:// Using the 'final' keyword to prevent overridingvoid Print() final {std::cout << "This is a derived class method." << std::endl;}};int main() {DerivedClass derivedObj;derivedObj.Print(); // Calling the method from DerivedClass// Attempting to override the final method in a subclass will result in a compilation errorclass AnotherDerivedClass : public DerivedClass {public:void Print() override {std::cout << "Another overridden method." << std::endl;}};return 0;}
In the below example, DerivedClass
can be inherited, but its Print
method cannot be overridden. The final
specifier prevents a method from being overridden in further derived classes.
#include <iostream>class BaseClass {public:virtual void Print() {std::cout << "This is a base class method." << std::endl;}};class DerivedClass : public BaseClass {public:void Print() final {std::cout << "This is a derived class method." << std::endl;}};int main() {DerivedClass derivedObj;derivedObj.Print();// Uncommenting the following class definition will result in a compilation error// class AnotherDerivedClass : public DerivedClass {// public:// void Print() override {// std::cout << "Another overridden method." << std::endl;// }// };return 0;}
There are a few reasons why we need to seal the classes:
It can be useful when we want to ensure that the behavior and structure of a class remain unchanged and not subject to modification by subclasses.
If a class is designed with a specific purpose and implementation, allowing it to be extended without restriction might lead to unforeseen issues or security vulnerabilities. In that case, sealing the classes can contribute to the security and stability of our code.
It signals to other developers that the class isn’t meant to be extended and should be used as is. This can help in maintaining a clear and well-defined API.
Some programming languages and compilers can make optimizations when they know that a class is sealed. This can lead to better performance since the compiler doesn’t need to account for potential subclassing.
These are the key points regarding sealed modifiers in C#, Java, and C++. Each language has its own way of achieving similar results, ensuring that certain classes or methods can’t be further extended, inherited, or overridden to maintain the integrity of our code.
It’s not always useful to seal the classes. Overuse of sealed classes can limit the flexibility and extensibility of our code. In many cases, allowing for controlled and well-designed inheritance can be beneficial. The decision to seal a class depends on the specific requirements and design goals of the application.
Free Resources