Mettermi la testa intorno all'immutabilità


13

Sono nuovo nella programmazione orientata agli oggetti e un concetto che mi sta prendendo da tempo per capire è l'immutabilità. Penso che la lampadina si sia spenta ieri sera, ma voglio verificare:

Quando trovo delle affermazioni secondo cui un oggetto immutabile non può essere modificato, sono perplesso perché, ad esempio, posso fare quanto segue:

NSString *myName = @"Bob";
myName = @"Mike";

Lì, ho appena cambiato myName, di tipo immutabile NSString. Il mio problema è che la parola "oggetto" può riferirsi all'oggetto fisico in memoria, o all'astrazione, "mioNome". La prima definizione si applica al concetto di immutabilità.

Per quanto riguarda la variabile, una definizione più chiara (per me) di immutabilità è che il valore di un oggetto immutabile può essere modificato solo cambiando anche la sua posizione in memoria, cioè il suo riferimento (noto anche come puntatore).

È corretto o mi sono ancora perso nei boschi?


13
Il tuo tipo non è un NSString, è un " puntatore a e NSString", che non è immutabile. Non so nulla di obiettivo C, ma credo nel tuo esempio, che @"Mike"sta creando una nuova istanza NSStringe assegnandola al puntatore , myName. Quindi non hai cambiato l'oggetto a cui myNamepuntava, proprio quello a cui puntava.
fwgx,

2
@fwgx Mettilo come risposta e otterrai il mio voto.
Gulshan,

Grazie a tutti per tutte le risposte, sono molto utili. Ora capisco che l'oggetto immutabile è il valore in memoria, non la variabile che lo indica.
Michael Mangold,

@Gulshan Fatto, vedi sotto ....
fwgx,

Per comprendere l'immutabilità, raccomando di imparare un linguaggio di programmazione che separa chiaramente il legame (ovvero dare nomi agli oggetti) con la mutabilità (cioè consentire che un nome venga riassegnato a un oggetto diverso). ML (sotto qualsiasi aspetto: SML, Ocaml, F #) è un buon esempio.
Gilles 'SO- smetti di essere malvagio' il

Risposte:


4

Sembra che tu stia andando nella giusta direzione, ma non l'hai ancora capito. Questo è sbagliato:

Lì, ho appena cambiato myName, di tipo immutabile NSString. Il mio problema è che la parola "oggetto" può riferirsi all'oggetto fisico in memoria, o all'astrazione, "mioNome".

Nel tuo frammento di codice, myNamenon è di tipo immutabile NSString, è di tipo mutabileNSString* (puntatore a NSString). Sembra che la cosa chiave che ti manca è capire che un puntatore è solo un altro valore e ha una vita completamente separata da ciò a cui punta (o cose, se lo cambi a metà della sua vita).

Tu dici:

... il valore di un oggetto immutabile può essere modificato solo cambiando la sua posizione in memoria, cioè il suo riferimento (noto anche come puntatore).

Questo è sbagliato. Un oggetto non possiede i puntatori che lo puntano, né la posizione della memoria di un oggetto è controllata o altrimenti influenzata da alcun puntatore ad esso.

Quindi, i due NSStringoggetti nel tuo esempio ( @"Bob"e @"Mike") sono completamente separati dalla myNamevariabile. Sono anche completamente separati l'uno dall'altro. Quando si cambia myNamepuntare @"Mike"invece di puntare a @"Bob", non si cambiano gli NSStringoggetti.


Per completezza, noterò che i garbage collector rendono questo più complesso in quanto le modifiche ai puntatori possono influire sugli oggetti a cui puntano (ed). Tuttavia, si tratta di un dettaglio di implementazione che non dovrebbe influire sul comportamento osservabile del codice.


17

Ti sei perso a parole. Immutabilità significa: fintanto che non cambi la variabile, essa "contiene" sempre lo stesso valore, indipendentemente da ciò che fai con le altre variabili.

Controesempio in C (un po 'semplificato, ipotizzando un'architettura che lo consenta):

 char *a = "Hello World";
 char *b = a;
 b[0] = 'Y';

Ora un "non contiene più" (ovvero indica ") la stringa" Hello World ", ma è invece" Yello World ".

Nelle lingue in cui le stringhe sono immutabili, come Java e (EDIT: sicuro) C #, non puoi farlo. Non c'è modo. Ciò significa che ogni parte del programma può tranquillamente mantenere un riferimento alla stringa e fare affidamento sul fatto che il suo contenuto non cambia mai; in caso contrario, dovrebbero crearne una copia solo per essere al sicuro.

Ma la variabile è ancora mutabile. Puoi lasciarlo puntare su un altro oggetto. È solo che l'oggetto stesso non cambierà alle tue spalle.


1
Tecnicamente puoi modificare il contenuto delle stringhe in C #, devi solo usare il unsafecodice.
Aaronaught,

1
Aaronaught: Grazie per le informazioni, hai ragione; per tutti coloro che ha bisogno di sapere come: msdn.microsoft.com/en-us/library/ms228599.aspx
user281377

10

Stai confondendo le variabili con gli oggetti. Le variabili possono essere utilizzate per memorizzare riferimenti ad oggetti, ma NON sono oggetti. Sono oggetti immutabili, non variabili, quindi puoi cambiare la variabile da un oggetto all'altro, ma non puoi cambiare gli attributi dell'oggetto se è immutabile.

Pensa all'oggetto come un vicino rumoroso e ubriaco. Se è ragionevole (mutevole), potresti essere in grado di bussare alla sua porta e convertirlo in uno stile di vita in cui non fa tanto rumore. Ma se è immutabile, il tuo unico cambiamento è sperare che qualcun altro si trasferisca!


3
Ho avuto alcuni vicini che mi sarebbe piaciuto silenziare.
Dave Nay,

Non penso che tu abbia bisogno del tuo esempio nel secondo paragrafo poiché la tua spiegazione è abbastanza buona. IMO l'esempio potrebbe confondere. Tuttavia +1 per una risposta concisa alla domanda del cap.
Paul McCabe,

@DaveNay: mi scuso per il gioco di parole invisibile. Non era previsto affatto.
Kilian Foth,

6

Una variabile non è un oggetto. Una variabile è un nome, che fa riferimento a un oggetto (o più in generale a un valore).

Ad esempio "il portiere" è un nome che usiamo per fare riferimento all'oggetto (persona) responsabile della difesa dell'obiettivo. Ma se sostituisco quella persona con un'altra (perché la prima è infortunata o quant'altro), la nuova persona viene ora definita "portiere".

La dichiarazione di assegnazione è ciò che rende mutabili le variabili (alcune lingue, come Haskell, non ce l'hanno e infatti usano variabili immutabili). Ti permette di ridefinire il significato di un nome e quindi riassegnare il valore.

Ora gli oggetti stessi possono essere immutabili. Qualche migliaio di anni fa si poteva pensare ai diamanti come immutabili. Non importa cosa hai fatto con un diamante, non puoi modificarlo. Sia che tu l'abbia chiamato waggawooga (che si traduce liberamente nella "più grande pietra lucente della nostra tribù") o che abbia smesso di chiamarlo in quel modo (perché ne hai trovato uno più grande), il diamante è rimasto lo stesso. Al contrario, il pezzo di legno che intagliavi in ​​immagini divertenti con il tuo waggawooga non è rimasto lo stesso. Si è rivelato mutevole. Anche se aveva sempre lo stesso nome.

Sia le variabili che i valori possono essere immutabili (indipendentemente). In questo caso, sono gli oggetti che sono immutabili. Una volta costruito un NSString, non è possibile modificarlo. Puoi chiamarlo nomi e passarlo in giro, ma rimarrà lo stesso. Al contrario, NSMutableStringpuò essere modificato dopo la creazione, ad esempio chiamando il setStringmetodo.


Adoro il confronto waggawooga!
Michael K,

Al fine di non confondere il poster originale più del necessario: anche se il punto in cui una variabile non è un oggetto è buono, una variabile non è in realtà definita come "un nome che si riferisce a un valore". Una variabile è probabilmente denominata e si riferisce a un percorso di archiviazione che contiene un valore. In molti linguaggi di programmazione non è necessario nominare le variabili e in molti linguaggi la stessa variabile può avere più di un nome.
Eric Lippert,

4

Penso che ti senti perso, perché stai mescolando due concetti: oggetto stesso e nome della variabile associato a quell'oggetto.

Gli oggetti immutabili non possono essere modificati. Periodo. Tuttavia, il nome della variabile (simbolo) associato a un oggetto immutabile, può essere modificato per essere associato a un altro oggetto immutabile.

In altre parole, quello che hai fatto in queste due righe è stato:

  1. creare un oggetto stringa immutabile con valore "Bob"
  2. associa il simbolo myNamea quell'oggetto
  3. creare un oggetto stringa immutabile con valore "Mike"
  4. associa il simbolo myNamea quell'oggetto

2

Il tuo tipo non è un NSString, è un " puntatore a un NSString", che non è immutabile. Non so nulla dell'obiettivo C, ma nel tuo esempio sto indovinando che @"Mike"sta creando una nuova istanza di NSStringe assegnandola al puntatore myName . Quindi non hai cambiato l'oggetto che myNameè stato rivolto a, proprio quello che si stava indicando.


0

Ecco un esempio di un oggetto mutabile: un array di charin C:

char str[10];

Posso modificare il contenuto del strmio cuore (purché non contenga più di 10 caratteri). Per essere riconosciuto come una stringa dalle funzioni della libreria di stringhe C, deve essere presente uno 0 finale, in modo che possa contenere stringhe di lunghezza massima di 9 caratteri:

strcpy(str, "hello"); // str now contains the string "hello\0"
strcpy(str, "world"); // str now contains the string "world\0"

str[0] = 'W';         // str now contains "World\0"

und so weiter .

Contrasto con un oggetto stringa in Java:

String foo = "Hello";

L' istanza di stringa (il blocco di memoria che contiene i caratteri 'H', 'e', ​​'l', 'l' e 'o') non può essere modificata; Non posso alterare nessuno dei contenuti di quella stringa. Quando scrivi qualcosa del genere

foo = foo + " World";

non stai aggiungendo "Mondo" alla fine dell'istanza "Ciao"; stai creando una nuova istanza , copiando "Hello World" e aggiornando fooper fare riferimento a quella nuova istanza di stringa.

foonon contiene l'istanza di stringa; si riferisce solo a quell'istanza (simile a un puntatore in C o Obj-C), quindi perché tipi come String sono chiamati tipi di riferimento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.