2012-07-01 4 views
48

Несомненно, упорядоченный набор является более конкретным случаем набора, поэтому почему NSOrderedSet наследует от NSObject, а не NSSet?Почему NSOrderedSet наследуется от NSSet?

+0

Если бы у разработчика.apple.com не было сразу, я бы взглянул на документы, потому что теперь у вас есть любопытные! Отличный вопрос. И, надеюсь, сайт Apple не будет оставаться слишком долго, не так ли? – WendiKidd

+2

(Отказ от ответственности: это чистая спекуляция и слишком неубедительная для меня, чтобы она действительно предоставляла ее в качестве ответа, но ...) «NSOrderedSet» - это более конкретный случай как «NSSet», так и «NSArray» , Это оба класса, а не протоколы, и в Objective-C нет множественного наследования. Итак, что вы выбираете? Есть аргумент для 'NSSet' из-за имени, но это может быть полностью NSUniqueArray', правильно? Играйте в это безопасно, бросайте их обоих ... –

+1

Я точно вижу, что вы говорите, но вы правы, что это не все так убедительно. Я бы интуитивно ожидал, что '[aSet intersectsSet: anOrderedSet]' будет возможным (но это не так, поскольку 'NSOrderedSet' не является подклассом' NSSet'), поэтому 'NSSet' делает гораздо более логичный выбор для суперкласса, чем' NSArray' - и даже если они сделали одинаково логичный выбор, потеря полиморфизма в любом случае не выбирая ни младшего варианта. – jhabbott

ответ

72

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

+0

Я думаю, что протоколы будут иметь больше смысла - это может быть больше связано с тем, что 'NSMutableSet' уже был определен и еще не использовал протокол для изменяемости.Не удалось ли добавить протокол, несмотря на то, что 'NSMutableSet' уже соответствует ему? – jhabbott

+0

Если бы они этого захотели, они могли бы добавить новый протокол, не нарушая ничего. Мы могли бы заметить, что это будет добавлено в будущем. –

+2

Отличный ответ, это было использовано в книге NSHipster, вот как я нашел этот вопрос ... знаете ли вы, почему книга NSHipster связывает эту проблему напрямую с NSSet, являющимся кластером классов? Я просто не вижу, как если NSSet был конкретный класс, что это было бы иначе, чем проблема с изменчивой копией, вы знаете? http://nshipster.com/nsorderedset/ –