Domanda

Avendo recentemente svolto un po' di sviluppo per iPhone, ho notato un interessante modello di progettazione utilizzato molto nell'SDK di iPhone, riguardante la mutabilità degli oggetti.

Sembra che l'approccio tipico sia quello di definire una classe immutabile NSFoo, e quindi derivarne un discendente mutevole NSMutableFoo.In generale, il NSFoo La classe definisce i membri dati, i getter e le operazioni di sola lettura, nonché i derivati NSMutableFoo aggiunge operazioni di setter e mutanti.

Avendo più familiarità con C++, non ho potuto fare a meno di notare che questo sembra essere completamente opposto a quello che farei scrivendo lo stesso codice in C++.Mentre tu certamente Potevo adottando questo approccio, mi sembra che un approccio più conciso sia crearne uno unico Foo class, contrassegnare i getter e le operazioni di sola lettura come const funzioni e implementano anche le operazioni e i setter mutabili nella stessa classe.Ti ritroveresti quindi con una classe mutabile, ma i tipi Foo const*, Foo const& ecc. sono tutti effettivamente l'equivalente immutabile.

Immagino che la mia domanda sia: la mia opinione sulla situazione ha senso?Capisco perché Objective-C fa le cose in modo diverso, ma ci sono vantaggi nell'approccio a due classi in C++ che mi sono perso?Oppure mi sto perdendo del tutto il punto?

Non è una domanda troppo seria, più per curiosità che per altro.

È stato utile?

Soluzione

Objective-C è troppo dinamico.In C++ la qualificazione const viene applicata in fase di compilazione e qualsiasi violazione della qualificazione const in fase di esecuzione (come la modifica di un oggetto qualificato const tramite un puntatore non qualificato const) è un comportamento indefinito.

In parte è lo stesso motivo per cui non esistono metodi privati ​​in Objective-C.Sei libero di inviare qualunque messaggio desideri a qualsiasi oggetto.L'invio in fase di runtime accetta un oggetto e un messaggio e risolve l'implementazione del metodo da invocare.

Se const gli oggetti qualificati possono solo invocare const metodi qualificati, rovinerebbe completamente la natura dinamica di Objective-C e Foundation perché tale controllo dovrebbe essere eseguito in fase di esecuzione (il primo controllo determinerebbe se il messaggio inviato si risolve in un'implementazione qualificata const per quella specifica istanza, e un altro controllo per determinare se l'istanza stessa era qualificata const).Consideriamo questo esempio teorico:

NSArray *mutableArray = [[NSArray alloc] init];

NSString *mutableString = @"I am a mutable string";
const NSString *immutableString = @"I am immutable because I am const-qual'd";

[mutableArray addObject:mutableString];
[mutableArray addObject:immutableString]; // what happens?!

// and what happens here (both immutable and mutable strings would respond
// to the same selectors because they are the same class):
[mutableArray makeObjectsPerformSelector:@selector(aMutableOperation)];

All'improvviso perdi dinamica.Così com'è ora, gli oggetti mutabili e immutabili possono stare insieme in una raccolta immutabile o mutabile.

Avere una sottoclasse mutabile mantiene la natura dinamica di Objective-C e semplifica il runtime.C'era un argomento simile qualche tempo fa sui metodi privati.

Altri suggerimenti

Pensieri ...

Mac, come sapete, in C ++, si può pensare di "A" e "A const", come due tipi diversi, con i loro soli rapporti essendo

  1. "A" e "A &" può essere inserito implicitamente in "A const" e "A const &", ecc ...
  2. "const A &" può essere const_cast a "A &", ecc ...

Le maniglie compilatore l'eredità e di propagazione del modificatore-tipo attraverso le espressioni, etc.

Direi che la gente NS scelto il ..Mutable .. convenzione per un paio di ragioni. La mia prima risposta è che io credo che quando NextStep era stato originariamente aperto la strada, C non hanno il supporto per "const" e ancora non ha Object-Orientamento. E ancora più importante, che volevano alcune ottimizzazioni nelle loro mutevole vs. implementazioni di oggetti immutabili. Ad esempio, in una classe di stringa immutabile come NSString, può essere utile per le stringhe "pool". Questo permette di stringhe duplicate da nebulizzare e per il processo di utilizzare potenzialmente meno memoria. (Ha alcuni aspetti negativi, ma ci sono sempre dei compromessi.)

In C ++ si potrebbe andare nella stessa direzione dalla prima comprensione copy-on-write . std :: string è detto di farlo.

Argomento interessante,
Will Bradley

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top