2012-07-01 10 views
48

Sicuramente un insieme ordinato è un caso più specifico di un insieme, quindi perché fa NSOrderedSet ereditare da NSObject piuttosto che NSSet?Perché NSOrderedSet non eredita da NSSet?

+0

Se developer.apple.com non fosse verso il basso in questo momento, mi piacerebbe andare a dare un'occhiata ai documenti, perché ora hai me curioso! Ottima domanda E speriamo che un sito Apple non rimanga per troppo tempo, giusto? – WendiKidd

+2

(Disclaimer: Questa è pura speculazione, e troppo poco convincente per me volerlo fornire effettivamente come risposta, ma ...) Un 'NSOrderedSet' è un caso più specifico sia di un' NSSet' che di un 'NSArray' . Quelle sono entrambe classi non protocolli e non c'è eredità multipla in Objective-C. Quindi, quale scegli? C'è un argomento per 'NSSet' a causa del nome, ma potrebbe essere stato completamente 'NSUniqueArray', giusto? Gioca sul sicuro, buttale entrambi ... –

+1

Vedo esattamente quello che stai dicendo, ma hai ragione che non è poi così convincente. Prevedo intuitivamente che '[aSet intersectsSet: anOrderedSet]' sia possibile (ma non lo è dato che 'NSOrderedSet' non è una sottoclasse di' NSSet'), quindi 'NSSet' rappresenta una scelta molto più logica per una superclasse di' NSArray' - e anche se hanno fatto scelte ugualmente logiche, perdere il polimorfismo rende comunque la scelta di nessuna opzione inferiore. – jhabbott

risposta

72

Sono passato attraverso l'interfaccia di NSSet e hai ragione, i set ordinati sembrano soddisfare Liskov substitution principle e potrebbero quindi ereditare da NSSet.

C'è un po 'di metodo che rompe questo: mutableCopy. Il valore di ritorno di mutableCopy deve essere un NSMutableSet, ma NSMutableOrderedSet dovrebbe ereditare da NSOrderedSet. Non puoi avere entrambi.

Lasciami spiegare con un po 'di codice. In primo luogo, diamo un'occhiata a un corretto comportamento delle NSSet e NSMutableSet:

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

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

Ora, facciamo finta NSOrderedSet eredita da NSSet, e NSMutableOrderedSet eredita da 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) 

E se NSMutableOrderedSet ereditato da NSMutableSet invece? Poi abbiamo un problema diverso:

//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) 

Nell'esempio 1, non sarebbe in grado di passare un NSOrderedSet in una funzione che si aspetta un NSSet perché il comportamento è diverso. Fondamentalmente, si tratta di un problema di compatibilità con le versioni precedenti.

Nell'esempio 2, non è possibile passare un NSMutableOrderedSet in una funzione che si aspetta un NSOrderedSet poiché il primo non eredita da quest'ultimo.

Tutto questo perché NSMutableOrderedSet non può ereditare da entrambi NSMutableSet e NSOrderedSet perché Objective-C non ha ereditarietà multipla. Il modo per aggirare questo è quello di creare protocolli per NSMutableSet e NSOrderedSet, perché quindi NSMutableOrderedSet può implementare entrambi i protocolli. Immagino che gli sviluppatori Apple fossero più semplici senza i protocolli aggiuntivi.

+0

Penso che i protocolli avrebbero più senso - potrebbe essere più a che fare con il fatto che il 'NSMutableSet' era già definito e non utilizzava già un protocollo per la mutabilità.Il protocollo non può ancora essere aggiunto nonostante il fatto che 'NSMutableSet' sia già conforme ad esso? – jhabbott

+0

Se lo volessero, potrebbero aggiungere un nuovo protocollo senza rompere nulla. Potremmo vederlo aggiunto in futuro. –

+2

Ottima risposta, questo è stato usato nel libro NSHipster, che è il modo in cui ho trovato questa domanda ... sai perché il libro NSHipster collega questo problema direttamente a NSSet essendo un cluster di classe ?, Semplicemente non vedo come se NSSet fosse una classe concreta che questo sarebbe diverso con il problema della copia mutevole, lo sai? http://nshipster.com/nsorderedset/ –