Конечно, упорядоченный набор является более конкретным случаем набора, поэтому почему NSOrderedSet наследует от NSObject, а не NSSet?
Почему NSOrderedSet не наследуется от NSSet?
Ответ 1
Я прошел через интерфейс NSSet, и вы правы, упорядоченные множества, похоже, удовлетворяют принципу подстановки Лискова и могли бы поэтому наследовать от NSSet.
Существует один маленький метод, который нарушает это: mutableCopy. Возвращаемое значение mutableCopy должно быть NSMutableSet, но NSMutableOrderedSet должно наследовать от NSOrderedSet. У вас не может быть обоих.
Позвольте мне объяснить с помощью некоторого кода. Сначала рассмотрим правильное поведение NSSet и NSMutableSet:
NSSet* immutable = [NSSet set];
NSMutableSet* mutable = [immutable mutableCopy];
[mutable isKindOfClass:[NSSet class]]; // YES
[mutable isKindOfClass:[NSMutableSet class]]; // YES
Теперь предположим, что NSOrderedSet наследует от NSSet, а NSMutableOrderedSet наследует от 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)
Что делать, если NSMutableOrderedSet унаследовано от NSMutableSet? Тогда возникает другая проблема:
//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)
В примере 1 вы не сможете передать NSOrderedSet в функцию, ожидающую NSSet, потому что поведение отличается. В принципе, это проблема обратной совместимости.
В примере 2 вы не можете передать NSMutableOrderedSet в функцию, ожидающую NSOrderedSet, потому что первая не наследует от последней.
Все это связано с тем, что NSMutableOrderedSet не может наследовать как от NSMutableSet, так и NSOrderedSet, потому что Objective-C не имеет множественного наследования. Способ обойти это состоит в том, чтобы создавать протоколы для NSMutableSet и NSOrderedSet, потому что тогда NSMutableOrderedSet может реализовать оба протокола. Я думаю, разработчики Apple, хотя это было проще, без дополнительных протоколов.