Should I recommend sealing classes by default?

C#Java.NetOop

C# Problem Overview


In a big project I work for, I am considering recommending other programmers to always seal their classes if they haven't considered how their classes should be subclassed. Often times, less-experienced programmers never consider this.

I find it odd that in Java and C# classes are non-sealed / non-final by default. I think making classes sealed greatly improves readability of the code.

Notice that this is in-house code that we can always change should the rare case occur that we need to subclass.

What are your experiences? I meet quite some resistance to this idea. Are people that lazy they could not be bothered to type sealed?

C# Solutions


Solution 1 - C#

Okay, as so many other people have weighed in...

Yes, I think it's entirely reasonable to recommend that classes are sealed by default.

This goes along with the recommendation from Josh Bloch in his excellent book Effective Java, 2nd edition:

> Design for inheritance, or prohibit it.

Designing for inheritance is hard, and can make your implementation less flexible, especially if you have virtual methods, one of which calls the other. Maybe they're overloads, maybe they're not. The fact that one calls the other must be documented otherwise you can't override either method safely - you don't know when it'll be called, or whether you're safe to call the other method without risking a stack overflow.

Now if you later want to change which method calls which in a later version, you can't - you'll potentially break subclasses. So in the name of "flexibility" you've actually made the implementation less flexible, and had to document your implementation details more closely. That doesn't sound like a great idea to me.

Next up is immutability - I like immutable types. I find them easier to reason about than mutable types. It's one reason why the Joda Time API is nicer than using Date and Calendar in Java. But an unsealed class can never be known to be immutable. If I accept a parameter of type Foo, I may be able to rely on the properties declared in Foo not to be changed over time, but I can't rely on the object itself not being modified - there could be a mutable property in the subclass. Heaven help me if that property is also used by an override of some virtual method. Wave goodbye to many of the benefits of immutability. (Ironically, Joda Time has very large inheritance hierarchies - often with things saying "subclasses should be immutable. The large inheritance hierarchy of Chronology made it hard to understand when porting to C#.)

Finally, there's the aspect of overuse of inheritance. Personally I favour composition over inheritance where feasible. I love polymorphism for interfaces, and occasionally I use inheritance of implementation - but it's rarely a great fit in my experience. Making classes sealed avoids them being inappropriately derived from where composition would be a better fit.

EDIT: I'd also like to point readers at Eric Lippert's blog post from 2004 on why so many of the framework classes are sealed. There are plenty of places where I wish .NET provided an interface we could work to for testability, but that's a slightly different request...

Solution 2 - C#

It is my opinion that architectural design decisions are made to communicate to other developers (including future maintenance developers) something important.

Sealing classes communicates that the implementation should not be overridden. It communicates that the class should not be impersonated. There are good reasons to seal.

If you take the unusual approach of sealing everything (and this is unusual), then your design decisions now communicate things that are really not important - like that the class wasn't intended to be inherited by the original/authoring developer.

But then how would you communicate to other developers that the class should not be inherited because of something? You really can't. You are stuck.

Also, sealing a class doesn't improve readability. I just don't see that. If inheritance is a problem in OOP development, then we have a much larger problem.

Solution 3 - C#

I'd like to think that I'm a reasonably-experienced programmer and, if I've learned nothing else, it's that I am remarkably bad at predicting the future.

Typing sealed is not hard, I just don't want to irritate a developer down the road (who could be me!) who discovers that a problem could be easily solved with a little inheritance.

I also have no idea how sealing a class makes it more readable. Are you trying to force people to prefer composition to inheritance?

Solution 4 - C#

© Jeffrey Richter

> There are three reasons why a sealed > class is better than an unsealed > class: > > - Versioning: When a class is originally sealed, it can change to > unsealed in the future without > breaking compatibility. However, once > a class is unsealed, you can never > change it to sealed in the future as > this would break all derived classes. > In addition, if the unsealed class > defines any unsealed virtual methods, > ordering of the virtual method calls > must be maintained with new versions > or there is the potential of breaking > derived types in the future. > - Performance: As discussed in the previous section, calling a virtual > method doesn’t perform as well as > calling a nonvirtual method because > the CLR must look up the type of the > object at runtime in order to > determine which type defines the > method to call. However, if the JIT > compiler sees a call to a virtual > method using a sealed type, the JIT > compiler can produce more efficient > code by calling the method > nonvirtually. It can do this because > it knows there can’t possibly be a > derived class if the class is sealed. > - Security: and predictability A class must protect its own state and not > allow itself to ever become corrupted. > When a class is unsealed, a derived > class can access and manipulate the > base class’s state if any data fields > or methods that internally manipulate > fields are accessible and not private. > In addition, a virtual method can be > overridden by a derived class, and the > derived class can decide whether to > call the base class’s implementation. > By making a method, property, or event > virtual, the base class is giving up > some control over its behavior and its > state. Unless carefully thought out, > this can cause the object to behave > unpredictably, and it opens up > potential security holes.

Solution 5 - C#

Frankly I think that classes not being sealed by default in c# is kind of weird and out of place with how the rest of the defaults work in the language.

By default, classes are internal. By default fields are private. By default members are private.

There seems to be a trend that points to least plausible access by default. It would stand to reason that a unsealed keyword should exits in c# instead of a sealed.

Personally I'd rather classes were sealed by default. In most ocassions when someone writes a class, he is not designing it with subclassing in mind and all the complexities that come along with it. Designing for future subclassing should be a conscious act and therefore I'd rather you explicitly have to state it.

Solution 6 - C#

There shouldn't be anything wrong in inheriting from a class.

You should seal a class only when theres a good reason why it should never be inherited.

Besides, if you seal them all, it will only decrease maintainability. Every time someone will want to inherit from one of your classes, he will see it is sealed, then he'll either remove the seal (mess with code he shouldn't have to mess with) or worse: create a poor implementation of your class for himself.

Then you'll have 2 implementations of the same thing, one probably worse than the other, and 2 pieces of code to maintain.

Better just keep it unsealed. No harm in it being unsealed.

Solution 7 - C#

I only seal classes if I am working on a reusable component that I intend to distribute, and I don't want the end user to inherit from it, or as a system architect if I know I don't want another developer on the team to inherit from it. However there is usually some reason for it.

Just because a class isn't being inherited from, I don't think it should automatically be marked sealed. Also, it annoys me to no end when I want to do something tricky in .NET, but then realize MS marks tons of their classes sealed.

Solution 8 - C#

This is a very opinionated question that's likely to garner some very opinionated answers ;-)

That said, in my opinion, I strongly prefer NOT making my classes sealed/final, particularly at the beginning. Doing this makes it very difficult to infer the intended extensibility points, and it's nearly impossible to get them right at the beginning. IMHO, overuse of encapsulation is worse than overuse of polymorphism.

Solution 9 - C#

Your house, your rule.

You can also have the complementary rule instead: a class that can be subclassed must be annotated; nobody should subclass a class that's not annotated so. This rule is not harder to follow than your rule.

Solution 10 - C#

"...consider[ing] how their classes should be sub classed..." shouldn't matter.

At least a half dozen times over the past few years I've found myself cursing some open source team or another for a sloppy mix of protected and private, making it impossible to simply extend a class without copying the source of the entire parent class. (In most cases, overriding a particular method required access to private members.)

One example was a JSTL tag that almost did what I wanted. I need to override one small thing. Nope, sorry, I had to completely copy the source of the parent.

Solution 11 - C#

I find that sealed / final classes are actually pretty rare, in my experience; I would certainly not recommend suggesting all classes be sealed / final by default. That specification makes a certain statement about the state of the code (i.e., that it's complete) that is not necessarily always true during development time.

I'll also add that leaving a class unsealed requires more design / test effort to make sure that the exposed behaviours are well-defined and tested; heavy unit testing is critical, IMO, to achieve a level of confidence in the behaviour of the class that appears to be desired by the proponents of "sealed". But IMO, that increased level of effort translates directly to a high level of confidence and to higher quality code.

Solution 12 - C#

I don't like that way to think. Java and c# are made to be OOP languages. These languages are designed in a way where a class can have a parent or a child. That's it.

Some people say that we should always start from the most restricting modifier (private, protected...) and set your member to public only when you use it externally. These people are ,to me, lazy and don't want to think about a good design at the beginning of the project.

My answer is: Design your apps in a good way now. Set your class to seal when it needs to be sealed and private when it needs to be private. Don't make them sealed by default.

Solution 13 - C#

The main purpose of a sealed class to take away the inheritance feature from the user so they cannot derive a class from a sealed class.Are you sure you want to do that. Or do you want to start having all classes as sealed and then when you need to make it inheritable you will change it .. Well that might be ok when every thing is in house and in one team but incase other teams in future use your dlls it will be not possible to recompile whole source code everytime a class needs to be unsealed .... I wont recommend this but thats just my opinion

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCarlo V. DangoView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#Jerry NixonView Answer on Stackoverflow
Solution 3 - C#48klocsView Answer on Stackoverflow
Solution 4 - C#Kirill PolishchukView Answer on Stackoverflow
Solution 5 - C#InBetweenView Answer on Stackoverflow
Solution 6 - C#Yochai TimmerView Answer on Stackoverflow
Solution 7 - C#CodingWithSpikeView Answer on Stackoverflow
Solution 8 - C#NateTheGreatView Answer on Stackoverflow
Solution 9 - C#irreputableView Answer on Stackoverflow
Solution 10 - C#Rodney GitzelView Answer on Stackoverflow
Solution 11 - C#Paul SonierView Answer on Stackoverflow
Solution 12 - C#Jean-Philippe LeclercView Answer on Stackoverflow
Solution 13 - C#AshView Answer on Stackoverflow