C# got it wrong. Java got it right.
C# doesn’t let you “seal” methods that aren’t overridden. Java allows you to mark any method as “final” – whether it’s an overridden method or not. This subtle detail has interesting implications.
The Gang of Four’s “Design Patterns: Elements of Reusable Object-Oriented Software” was published in 1994—many years before C# was first released and just two years before Java was released. (Although, most of the code in the book was presented in C++.) The book presents the “Template Method” behavioral pattern. Template methods define the “framework” of an algorithm and leave subclasses to define the behavior. Unfortunately, if you cannot mark a template method as ‘final’ (or ‘sealed’ in C#), it enables subclasses to—potentially by accident—change the behavior of the template method.
Here’s a template method in action, written in JS++, to demonstrate how this might be undesirable:
abstract class Model { abstract public bool validate(); abstract protected void saveTemplate(IDatabase db); public final void save(IDatabase db) { if (!this.validate()) { throw new ValidationException(); } this.saveTemplate(db); } }
In the above class, the template method (“save”) is marked as ‘final’. Without ‘final’, an overriding method (or overwriting method, to use JS++ terminology) can potentially forget to perform business object validation before altering the database. This can lead to potential bugs and security threats.
Beginning with the next release of JS++, you will be able to mark any method as ‘final’.