Почему NSOrderedSet не наследуется от NSSet?

Конечно, упорядоченный набор является более конкретным случаем набора, поэтому почему NSOrderedSet наследует от NSObject, а не 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, хотя это было проще, без дополнительных протоколов.