views:

1232

answers:

8

A large number of classes in the .Net framework are marked as 'sealed', preventing you from inheriting those classes with your own. Surely this goes against the nature of object orientation, where you can extend and redefine the behaviour of existing objects.

Is there a good reason for the existence of the 'sealed' keyword?

As an example, NotifyCollectionChangedEventArgs in Silverlight is sealed. I wanted to create my own version of ObservableCollection that supported AddRange and RemoveRange, but the Silverlight version of NCCEA doesn't provide a constructor that supports multiple items for the NewItems and OldItems properties, which are already defined as ILists. Usually, I'd just extend the class with my own variant that overrode the NewItems and OldItems properties, but in this case I can't and I can see no reason why that should be the case.

+1  A: 

The short answer is, because Microsoft said so. The longer answer is that Microsoft has provided a mechanism to extend sealed classes, called extension methods.

In general, it's a bad idea to extend classes which which you don't have source code to. For example, you don't know what calling base method does to the internal data of the object. Yes, you can use reflector or whatever to figure it out, but in general it's much better to use composition or extension methods.

You also have to consider what inheritence actually is. It's not just a way to alter the class, it also provides polymorphism. What if you change the semantics of, say, the string class, then you pass your new string class to an object that expects a string to act in a specific way? sealed essentially enforces the contract that this object will always work the way you expect it to.

Mystere Man
But if I have a new SuperString class that extends string, and it doesn't behave the way other classes expect it to, then surely that's my problem as the implementor of the SuperString class.It seems silly to seal a class just because another developer *might* break it.
X-Cubed
That would be fine if you were only using a string in your own code. But classes like String are used throughout the framework. Microsoft wants to make sure they don't change for their own usage.
Mystere Man
+1  A: 

While I do agree that .NET probably seals too much, it's generally to protect the integrity of an ecosystem. When one of your top priorities is to keep your overall framework/API/runtime stable, and there are somewhat fragile interdependencies between classes, it may be safest to prevent people from overriding that behavior and inadvertently destabilizing core functionality.

Though again, I do tend to feel that the .NET team seals too many classes. Sealing can sometimes be simple laziness on the part of the developer because a proper class design would be too much work.

Rex M
+4  A: 

This answer from a somewhat related question I asked today might help clarify the purposes of sealing a class:

I found myself asking that same question until I started working on reusable libraries of my own. Many times you wind up with certain classes that just cannot be extended without requiring obscure or arcane sequences of calls from the implementor.

When allowing your class to be extended, you have to ask: if a developer extends my class, and passes this new class to my library, can I transparently work with this new class? Can I work properly with this new class? Is this new class really going to behave the same?

I've found that most of the time the sealed classes in the .Net Framework have certain under-the-hood requirements that you aren't aware of, and that given the current implementation cannot be safely exposed to subclasses.

http://stackoverflow.com/questions/554145/liskov-substition-and-composition/554192#554192

Now follow that link and upvote the actual author.

FlySwat
+2  A: 

Without digging too deeply, understand that Microsoft favors sealing a class when there are potential security, maintainability or backwards-compatibility issues that it will have to deal with downstream. For example, System.String is sealed for security and performance reasons.

In this particular case, you'd need to ask a Microsoft developer why they chose to seal that class. However, the architectural guidance literature I've been reading lately tends to favor an approach of "seal unless you know it will need to be extended." This literature tends to espouse using extension methods where possible. (I'm not saying I agree with it; I'm just saying that's what I've been reading lately.)

Even if the class weren't sealed, the properties in question might have been left not virtual, which would still leave you up the creek here.

In your specific scenario, I'd go with extension methods with your own unique names. It's about all you can do.

John Rudy
+10  A: 

Designing classes and frameworks to be extensible isn't trivial, and inheritance isn't the single principle of Object Oriented programming.

So sealed preserves the developers intentions and makes their life easier. It allows the developer to control how the class is used, and allows them to make internal changes without worrying about breaking changes to code in the wild.

One principle is that you should seal any leaf class by default. Then when you create an unsealed class it forces you to think about extensibility.

Robert Paulson
A: 

It depends, there are classes that are intended to be just instantiated (inheritance, if exists, is used just to simplify the implementation), other classes are intended to be inherited to provide a spesific implementation.

Sealed classes have some advantages:

  • they don't have any virtual methods, so they don't have to worry about non-"exception- safe" implemented overriding methods.
  • If a class is immutable it can preserve and guarantee the immutability.

Otherwise if you want to decorate a sealed class with "comfort" methods use the extension methods (C# 3.0).

Michael Damatov
A: 

Just because something is an object, it doesn't mean it always should be wide open for everybody to extend or redefine it's behavior.

A good analogy would be a door and a lock. A door's nature is to let people to pass through it, that's what it's built for. Yet, most doors are designed with locks that can limit the ability of people to pass through them. The decision whether a door has a lock and whether that lock is locked by default is left to the architect of the room, based on what's in the room and who should have access to it, not on the fact that it's a door.

Of course, it can be frustrating if most of the doors in particular building are locked by default, especially if there's one you really want to go through. :-) I've been there myself and I've asked the same question. The short answer is that sometimes when designing a complex framework, people tend to err a little bit on the more cautios side and have classes sealed by default, unless there is explicit scenario that requires them to be extended.

Franci Penov
+1  A: 

I would suggest that there is no good reason for sealing classes other than to protect the ignorant -err, I mean innocent. You know the old saying, "given them enough rope and they will hang themselves". Let them sway I say. Perhaps this is my C++ background, but I am quite comfortable knowing that I have the power to completely stuff things up if I am not diligent.

I tend to program by interface. The interfaces are of course public and any one is free to provide their own implementation that adheres to the contract expressed by the interface. My concrete classes that implement these interfaces tend to be a private concern and are marked internal and/or private. I don't feel that I need to seal such classes.

Where code reuse is desirable, I avoid reuse through inheritance, favouring composition and other techniques.

Sealing may also be valid on types that are considered plain-old-data types, but I'm not convinced wither way on this.

Daniel Paull