I hate sealed classes!!!

Note: this entry has moved.

Sealed keyword is by far the most annoying showstopper to extensibility. I hate it so much. I wish there was an FxCop rule that would enforce that:
1 - If a class is sealed, then it *must* implement an interface that extenders can implement to hook custom implementations.
2 - The sealed class cannot be used *anywhere* in an "if (foo is MyDamnSealedClass)" statement. The required interface from 1) must be used instead.
3 - If a method is sealed, the class should be sealed too, or an equivalent method called from the sealed one is provided for inheritors (implementation of the template method pattern). There's no point in providing a non-sealed class where it's most important behavior (say an Execute method in a Command class or something like that) is sealed and there's no way to change its core behavior.

Although the third one is a little bit extreme, the first two are a MUST. Another day I'll tell you where I found a few key such annoying combinations...

7 Comments

  • Sealed classes have a purpose, and I think who you really hate is the person who sealed that class. It's all a matter of designing the classes. If you're complaining about sealed classes in the Framework, they're there for a reason. From what I've seen in good class libraries, the sealed classes are usually singletons and low-level internal stuff that are really not meant to be inherited.



    For #2 and #3, I haven't really encountered or used the "is" operator on a sealed class, probably because I usually do this to check if an instance is of a parent type. Sealed methods...hmm..need to read on this one.

  • I'm not talking about those classes in the .NET framework, but in general, whenever you create a framework of any kind. Singletons have nothing to do with sealed in my experience, neither are they necessarily any indication of low level stuff, IMO. I can give you examples in a couple weeks more ;)

  • Okay, sorry for not being clear, but I mentioned singletons and low-level classes only as examples of classes that are exposed in the library but cannot be inherited. I agree that these have nothing to do with being sealed or not.



    I still believe that the mindset when designing libraries is resistance to sealing classes. The MSDN docs also says the same:

    <ul><li>

    <p>The class is static.</p>

    </li><li>

    <p>The class contains inherited protected members with security-sensitive information.</p>

    </li><li>

    <p>The class inherits many virtual members and the development and testing costs for sealing each member are significantly more costly than sealing the entire class.</p>

    </li><li>

    <p>The class is an attribute that requires fast searching using reflection. Sealing an attribute improves reflection's performance when retrieving attributes.</p>

    </li></ul>

    I guess coders should be more careful in designing libraries and only seal classes when necessary.

  • Sorry to disagree, Dan, but I'm firmly of the opinion that sealing should be your default mode. Unless you specifically design a class to cope with being inherited, you're asking for trouble leaving it unsealed. How can any of your classes know that an object passed into them is really going to keep to its half of the API contract if it could be an instance of a subclass? How would you be able to write any code if, for example, System.String wasn't sealed?



    Leaving a class unsealed but not allowing subclasses to do anything useful is an even worse sin, of course - one that many of the .NET framework classes are guilty of. I've developed a few tricks for creating useful subclasses off .NET controls which I've collectively started calling 'lying to your parents'. They aren't pretty, and a few useful virtual methods in the baseclasses would make them a lot more helpful.



  • Hi James!

    >How would you be able to write any code if, for example, System.String wasn't sealed?

    Exactly the same way you write code that receives a Stream even if it's abstract and non-sealed and generally you don't care what type of stream it is.



    If you only open up your classes when you designed them to be inherited, you have to think of all possible extensions and uses that people can possibly want from your classes. This is pretty much an impossible task, and if I ever think I can do that (guess what the world wants to use my classes for), I'll be a hell of an arrogant.



    The truth is that people will use your stuff in ways you never imagined, leading to creative and interesting freatures that you would have otherwise forbidden by design. Of course they may break the contract. If they do so, they are on their own. But I prefer to leave them that freedom.

  • SqlConnection class (and other connections classes) is a great example of bad use of sealed keyword. I can't find any good explanation why it is done that way.

    I takes me a while until I found a way to keep conenction string in one place and still use it in designer without inheritance.

    And no I don't want to use config file - it's windows.forms control embeded in IE.

  • (@James): The default mode should NOT be sealed, this is typical of the "I know best" attitude that plagues the framework with sealed classes in the first place.



    It is not the responsibility of the original designer to ensure that future development can't break his classes or heirarchy.



    That is the responsibility of people subclassing your objects. If they choose to inherit your object they gain your API contract and if they then choose to break it that is their problem.



    [)amien

Comments have been disabled for this content.