web-dev-qa-db-ja.com

NSOrderedSetがNSSetから継承しないのはなぜですか?

確かに、順序集合は集合のより具体的なケースですが、なぜNSOrderedSetNSObjectではなくNSSetから継承するのでしょうか。

50
jhabbott

NSSetのインターフェースを通過しましたが、その通り、順序集合は リスコフの置換原則 を満たしているように見えるため、NSSetから継承できます。

これを破る小さな方法が1つあります:mutableCopymutableCopyの戻り値はNSMutableSetである必要がありますが、NSMutableOrderedSetNSOrderedSetから継承する必要があります。両方を持つことはできません。

いくつかのコードで説明しましょう。まず、NSSetNSMutableSetの正しい動作を見てみましょう。

NSSet* immutable = [NSSet set];
NSMutableSet* mutable = [immutable mutableCopy];

[mutable isKindOfClass:[NSSet class]]; // YES
[mutable isKindOfClass:[NSMutableSet class]]; // YES

ここで、NSOrderedSetNSSetから継承し、NSMutableOrderedSetNSOrderedSetから継承しているとしましょう。

//Example 1
NSOrderedSet* immutable = [NSOrderedSet orderedSet];
NSMutableOrderedSet* mutable = [immutable mutableCopy];

[mutable isKindOfClass:[NSSet class]]; // YES
[mutable isKindOfClass:[NSMutableSet class]]; // NO (this is the problem)

代わりにNSMutableOrderedSetNSMutableSetから継承された場合はどうなりますか?次に、別の問題が発生します。

//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を渡すことはできません。

これはすべて、Objective-Cには多重継承がないため、NSMutableOrderedSetNSMutableSetNSOrderedSetの両方から継承できないためです。これを回避する方法は、NSMutableSetNSOrderedSetのプロトコルを作成することです。これは、NSMutableOrderedSetが両方のプロトコルを実装できるためです。 Apple開発者は、追加のプロトコルがなくても簡単だったと思います。

76
Tom Dalling