Несомненно, упорядоченный набор является более конкретным случаем набора, поэтому почему NSOrderedSet
наследует от NSObject
, а не NSSet
?Почему NSOrderedSet наследуется от NSSet?
ответ
Я прошел через интерфейс NSSet
, и вы правы, упорядоченные наборы, похоже, удовлетворяют Liskov substitution principle и могут поэтому наследовать от 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, хотя это было проще без дополнительных протоколов.
Я думаю, что протоколы будут иметь больше смысла - это может быть больше связано с тем, что 'NSMutableSet' уже был определен и еще не использовал протокол для изменяемости.Не удалось ли добавить протокол, несмотря на то, что 'NSMutableSet' уже соответствует ему? – jhabbott
Если бы они этого захотели, они могли бы добавить новый протокол, не нарушая ничего. Мы могли бы заметить, что это будет добавлено в будущем. –
Отличный ответ, это было использовано в книге NSHipster, вот как я нашел этот вопрос ... знаете ли вы, почему книга NSHipster связывает эту проблему напрямую с NSSet, являющимся кластером классов? Я просто не вижу, как если NSSet был конкретный класс, что это было бы иначе, чем проблема с изменчивой копией, вы знаете? http://nshipster.com/nsorderedset/ –
Если бы у разработчика.apple.com не было сразу, я бы взглянул на документы, потому что теперь у вас есть любопытные! Отличный вопрос. И, надеюсь, сайт Apple не будет оставаться слишком долго, не так ли? – WendiKidd
(Отказ от ответственности: это чистая спекуляция и слишком неубедительная для меня, чтобы она действительно предоставляла ее в качестве ответа, но ...) «NSOrderedSet» - это более конкретный случай как «NSSet», так и «NSArray» , Это оба класса, а не протоколы, и в Objective-C нет множественного наследования. Итак, что вы выбираете? Есть аргумент для 'NSSet' из-за имени, но это может быть полностью NSUniqueArray', правильно? Играйте в это безопасно, бросайте их обоих ... –
Я точно вижу, что вы говорите, но вы правы, что это не все так убедительно. Я бы интуитивно ожидал, что '[aSet intersectsSet: anOrderedSet]' будет возможным (но это не так, поскольку 'NSOrderedSet' не является подклассом' NSSet'), поэтому 'NSSet' делает гораздо более логичный выбор для суперкласса, чем' NSArray' - и даже если они сделали одинаково логичный выбор, потеря полиморфизма в любом случае не выбирая ни младшего варианта. – jhabbott