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.