Why doesn't NSOrderedSet inherit from NSSet?

Objective CIosNssetNsorderedset

Objective C Problem Overview


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

Objective C Solutions


Solution 1 - Objective C

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.

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
QuestionjhabbottView Question on Stackoverflow
Solution 1 - Objective CTom DallingView Answer on Stackoverflow