2012-05-10 11 views
9

Supponiamo di creare una classe Objective-C che rappresenta una frazione e di voler creare versioni immutabili e mutevoli.Qual è il modo più efficiente per creare versioni immutabili e mutabili di una classe obiettivo-c?

Seguendo gli schemi nel framework Foundation, è possibile che si veda il metodo fractionByAddingFraction: nella versione immutable e addFraction: nella versione mutabile.

Il paradosso che sto incontrando è come includere la logica di aggiunta di una sola volta tra le due classi. Sembra che il metodo immodificabile fractionByAddingFraction: debba conoscere (e utilizzare) il metodo mutabile addFraction: per evitare la duplicazione del codice, e tuttavia includere i metodi mutabili nell'implementazione della classe immutabile significa che potrebbero essere chiamati sull'immutabile oggetto, che sconfigge il punto.

Una breve spiegazione (o, meglio ancora, una continuazione di questo esempio semplificato) sarebbe molto apprezzata!

+4

L'esempio di classe sembra rappresentare un oggetto _valore_, quindi non penso che dovresti fornire una versione mutabile per questo. __attialo renderlo immutabile .__ –

+0

@ Jordão Per questo particolare esempio, hai perfettamente ragione. Ho solo sentito che questo era il modo più semplice e conciso per spiegare la mia confusione sul concetto in generale (in quanto riguarda classi più complicate). Qualche idea su come si farebbe a prescindere? – user1385983

risposta

3

Il tuo approccio è corretto (se hai davvero bisogno di una sottoclasse mutabile, che dovresti evitare a meno che tu non ne abbia effettivamente bisogno). Non sono del tutto chiaro dove possa arrivare la confusione. Si implementerebbe più facilmente addFraction: utilizzando fractionByAddingFraction:. Sarebbe un po 'inefficiente, ma questa è la direzione che avrebbe più senso. Qualcosa di simile:

- (void)addFraction:(Fraction *)anotherFraction { 
    Fraction *newFraction = [self fractionByAddingFraction:anotherFraction]; 
    self.internalStuff = newFraction.internalStuff; 
} 

ma in genere si sarebbe probabilmente gestire in modo più efficiente con una certa _GetInternalStuffByAddingInternalStuffs() funzione privata che entrambe le classi avrebbero usato.

+0

Grazie per i suggerimenti. Avevo evitato il primo approccio semplicemente perché, come hai detto, può essere inefficiente creare un nuovo oggetto ogni volta che vengono modificati i suoi componenti. La tua idea di creare una funzione privata sembra una buona alternativa, tuttavia mi chiedo dove si posizionerà idealmente la funzione per essere accessibile alle implementazioni di entrambe le classi, ma inaccessibile a qualsiasi altra cosa (che esclude di inserirlo in un'intestazione)? – user1385983

+0

Questo in genere viene eseguito con un'intestazione privata come Fraction + Private.h. Si noti che si potrebbe ancora voler considerare di abbandonare la forma mutevole se si tratta di questo genere di cose. Si noti come NSNumber non ha una forma mutevole. A meno che non ne creiate molti molto velocemente, la semplicità e la sicurezza del thread degli oggetti di valore li rendono molto attraenti. Anche se li fai molto velocemente, puoi metterne in cache alcuni. NSNumber memorizza nella cache gli interi -1-12 come singletons come ricordo. Puoi fare quel tipo di memorizzazione nella cache più facilmente con oggetti immutabili. Ma quanto sopra è come lo gestisci quando hai bisogno di mutabilità. –

+0

Ricorda che puoi andare a vedere come sono implementati gli oggetti CoreFoundation sottostanti: http://opensource.apple.com/source/CF/CF-635/CFArray.c. –

0

Le principali implementazioni delle collezioni della Fondazione imbrogliano: c'è solo un'implementazione, che è una sottoclasse di NSMutableFoo, e ha un flag di mutabilità privato. Questo significa che il codice client non può testare se un particolare oggetto è mutabile o meno, ma non sarebbe comunque una buona idea tranne forse per il debugging e le asserzioni.

+0

Sto capendo correttamente che 'NSFoo' sarebbe una sottoclasse di 'NSMutableFoo', e che 'NSMutableFoo' conterrà tutti i metodi per entrambe le classi, tuttavia limiterà la sua capacità di sottoclasse immutabile di usare quelle mutabili basate sulla bandiera privata? – user1385983

+0

'NSFoo' non è una sottoclasse di' NSMutableFoo', no. La relazione è generalmente 'NSFoo' ←' NSMutableFoo' ← 'NSCFFoo', dove' NSCFFoo' è un'implementazione concreta. I metodi di muting di 'NSCFFoo' controllano il flag mutabile e generano un'eccezione se è immutabile. (La realtà è in realtà più complessa di questo a causa di un ponte senza pedaggio, ma è così che funzionerebbe senza coinvolgere CF.) Per le tue classi, probabilmente chiamerai la sottoclasse concreta qualcosa come 'XYConcreteFoo'. –

Problemi correlati