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

- 18,461
- 9
- 58
- 95
-
If developer.apple.com weren't down right now, I'd go take a look at the docs because now you've got me curious! Excellent question. And hopefully an Apple site won't stay down for too long, right? – WendiKidd Jul 01 '12 at 01:53
-
2(Disclaimer: This is pure speculation, and too unconvincing for me to want to actually provide it as an answer, but...) An `NSOrderedSet` is a more-specific case of both an `NSSet` and an `NSArray`. Those are both classes not protocols, and there's no multiple inheritance in Objective-C. So, which do you pick? There's an argument for `NSSet` because of the name, but it could totally have been `NSUniqueArray`, right? Play it safe, ditch them both... – Kristian Glass Jul 01 '12 at 01:56
-
1I see exactly what you're saying, but you're right that it's not all that convincing. I'd intuitively expect `[aSet intersectsSet:anOrderedSet]` to be possible (but it's not since the `NSOrderedSet` is not a subclass of `NSSet`), so `NSSet` makes a far more logical choice for a superclass than `NSArray` - and even if they made equally logical choices, losing the polymorphism makes choosing neither an inferior option anyway. – jhabbott Jul 01 '12 at 02:33
-
Good question. I had to think hard about this one for a while. – Tom Dalling Jul 01 '12 at 02:56
1 Answers
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.

- 23,305
- 6
- 62
- 80
-
I think the protocols would make more sense - it could be more to do with the fact that the `NSMutableSet` was already defined and didn't already use a protocol for the mutability. Couldn't the protocol still be added despite the fact that `NSMutableSet` already conforms to it? – jhabbott Jul 01 '12 at 03:00
-
If they wanted to, they could add a new protocol without breaking anything. We might see it added in the future. – Tom Dalling Jul 01 '12 at 03:04
-
3Great answer, this was used in NSHipster book, which is how I found this question... do you know why the NSHipster book links this issue directly to NSSet being a class cluster?, I simply don't see how if NSSet was a concrete class that this would be any different with the mutable copy issue, do you know? http://nshipster.com/nsorderedset/ – Oscar Gomez Mar 03 '14 at 17:30
-
1@OscarGomez Oh cool, I didn't notice this in NSHipster. When they mention class clusters, I think they are specifically talking about how clusters (such as NSSet) often contain a mutable and immutable public class, which is the core of the problem. I don't think they're implying that private cluster subclasses affect the issue. – Tom Dalling Mar 04 '14 at 01:37
-