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