Why doesn't NSOrderedSet inherit from NSSet?

Surely an ordered set is a more-specific case of a set, so why does NSOrderedSet inherit from NSObject rather than NSSet?


I went through the interface of NSSet and you're right, ordered sets appear to satisfy the Liskov substitution principle and could therefor inherit from NSSet.

There is one little method that breaks this: mutableCopy. The return value of mutableCopy must be an NSMutableSet, but NSMutableOrderedSet should inherit from NSOrderedSet. You can't have both.

Let me explain with some code. First, let's look at the correct behaviour of NSSet and NSMutableSet:

NSSet* immutable = [NSSet set];
NSMutableSet* mutable = [immutable mutableCopy];

[mutable isKindOfClass:[NSSet class]]; // YES
[mutable isKindOfClass:[NSMutableSet class]]; // YES

Now, let's pretend NSOrderedSet inherits from NSSet, and NSMutableOrderedSet inherits from NSOrderedSet:

//Example 1
NSOrderedSet* immutable = [NSOrderedSet orderedSet];
NSMutableOrderedSet* mutable = [immutable mutableCopy];

[mutable isKindOfClass:[NSSet class]]; // YES
[mutable isKindOfClass:[NSMutableSet class]]; // NO (this is the problem)

What if NSMutableOrderedSet inherited from NSMutableSet instead? Then we get a different problem:

//Example 2
NSOrderedSet* immutable = [NSOrderedSet orderedSet];
NSMutableOrderedSet* mutable = [immutable mutableCopy];

[mutable isKindOfClass:[NSSet class]]; // YES
[mutable isKindOfClass:[NSMutableSet class]]; // YES
[mutable isKindOfClass:[NSOrderedSet class]]; // NO (this is a problem)

In Example 1, you wouldn't be able to pass an NSOrderedSet into a function expecting an NSSet because the behaviour is different. Basically, it's a backwards compatibility problem.

In Example 2, you can't pass an NSMutableOrderedSet into a function expecting an NSOrderedSet because the former doesn't inherit from the latter.

All of this is because NSMutableOrderedSet can't inherit from both NSMutableSet and NSOrderedSet because Objective-C doesn't have multiple inheritance. The way to get around this is to make protocols for NSMutableSet and NSOrderedSet, because then NSMutableOrderedSet can implement both protocols. I guess the Apple developers just though it was simpler without the extra protocols.