Getting My Head Around Immutability

12

Sono nuovo nella programmazione orientata agli oggetti e un concetto che mi sta prendendo un po 'di tempo da cogliere è immutabilità. Penso che la lampadina sia esplosa ieri sera ma voglio verificare:

Quando mi imbatto in dichiarazioni che un oggetto immutabile non può essere cambiato, sono perplesso perché posso, ad esempio, fare quanto segue:

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

Lì, ho appena cambiato myName, di tipo immistrable NSString. Il mio problema è che la parola "oggetto" può riferirsi all'oggetto fisico in memoria o all'astrazione "myName". 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 cambiando anche la sua posizione nella memoria, cioè il suo riferimento (anche conosciuto come il suo puntatore).

È corretto, o sono ancora perso nel bosco?

    
posta Michael Mangold 29.06.2011 - 14:25
fonte

7 risposte

4

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

There, I just changed myName, of immutable type NSString. My problem is that the word, "object" can refer to the physical object in memory, or the abstraction, "myName."

Nel tuo snippet di codice, myName non è di tipo immutabile NSString , è di mutevole tipo NSString* (puntatore a NSString). Sembra che la cosa fondamentale che ti manca sia capire che un puntatore è solo un altro valore e ha una vita completamente separata dalla cosa a cui punta (o cose, se la modifichi in parte per tutta la sua durata).

Dici:

... the value of an immutable object can only be changed by also changing its location in memory, i.e. its reference (also known as its pointer).

Questo è sbagliato. Un oggetto non proprio i puntatori che puntano ad esso, né la locazione di memoria di un oggetto controllata o comunque influenzata da alcun puntatore ad esso.

Quindi, i due oggetti NSString nell'esempio ( @"Bob" e @"Mike" ) sono completamente separati dalla variabile myName . Sono anche completamente separati l'uno dall'altro. Quando cambi myName per puntare a @"Mike" invece di puntare a @"Bob" , non stai cambiando gli oggetti NSString .

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

    
risposta data 29.06.2011 - 15:05
fonte
17

Sei perso a parole. Immutabilità significa: finché non modifichi la variabile, essa "contiene" sempre lo stesso valore, non importa ciò che fai con altre variabili.

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

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

Ora non più "contiene" (cioè punti alla) "Hello World", ma invece è "Yello World".

Nelle lingue in cui le stringhe sono immutabili, come Java e (EDIT: safe) C #, non è possibile 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; altrimenti, dovrebbero creare una copia solo per essere al sicuro.

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

    
risposta data 29.06.2011 - 14:33
fonte
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 a un altro, ma non puoi cambiare gli attributi dell'oggetto se è immutabile.

Pensa all'oggetto come un vicino rumoroso e ubriaco. Se è ragionevole (mutabile), 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 muova!

    
risposta data 29.06.2011 - 14:58
fonte
6

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

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

L'istruzione di assegnazione è ciò che rende mutabili le variabili (alcuni linguaggi come Haskell non ce l'hanno e infatti usano variabili immutabili). 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 che i diamanti fossero immutabili. Non importa cosa hai fatto con un diamante, non puoi modificarlo. Sia che lo chiami waggawooga (si traduca liberamente in "la più grande pietra lucente della nostra tribù") o 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 hai usato per scolpire in immagini divertenti con il tuo waggawooga non è rimasto lo stesso. Si è dimostrato mutabile. Anche se avesse 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 creato un NSString , non puoi modificarlo. Puoi chiamarlo e passarlo, ma rimarrà lo stesso. Al contrario, NSMutableString può essere modificato dopo la creazione, ad esempio chiamando il metodo setString .

    
risposta data 29.06.2011 - 15:02
fonte
4

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

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

In altre parole, ciò che hai fatto in queste due righe era:

  1. crea un oggetto stringa immutabile con valore "Bob"
  2. associa il simbolo myName a quell'oggetto
  3. crea un oggetto stringa immutabile con valore "Mike"
  4. associa il simbolo myName a quell'oggetto
risposta data 29.06.2011 - 14:55
fonte
2

Il tuo tipo non è un NSString , è un " puntatore a un NSString ", che non è immutabile. Non so nulla dell'obiettivo C, ma suppongo nel tuo esempio che @"Mike" stia creando una nuova istanza di NSString e assegnandola al puntatore myName . Quindi non hai cambiato l'oggetto che myName era puntare a, solo a cosa puntava.

    
risposta data 29.06.2011 - 21:52
fonte
0

Ecco un esempio di oggetto mutabile: una matrice di char in C:

char str[10];

Posso cambiare i contenuti di str nel contenuto del mio cuore (purché non sia più di 10 caratteri). Affinché possa essere riconosciuto come una stringa dalle funzioni della libreria stringa C, deve esserci uno 0 finale, quindi può contenere stringhe lunghe fino a 9 caratteri:

strcpy(str, "hello"); // str now contains the string "hello
String foo = "Hello";
" strcpy(str, "world"); // str now contains the string "world
foo = foo + " World";
" str[0] = 'W'; // str now contains "World
char str[10];
"

und so weiter .

Contrasto con un oggetto stringa in Java:

strcpy(str, "hello"); // str now contains the string "hello
String foo = "Hello";
" strcpy(str, "world"); // str now contains the string "world
foo = foo + " World";
" str[0] = 'W'; // str now contains "World%pre%"

La stringa istanza (il frammento di memoria che contiene i caratteri "H", "e", "l", "l" e "o") non può essere modificato; Non riesco a modificare nessuno dei contenuti di quella stringa. Quando scrivi qualcosa come

%pre%

non aggiungi "Mondo" alla fine dell'istanza "Ciao"; stai creando una nuova istanza , copiando "Hello World" su di essa e aggiornando foo per fare riferimento a questa nuova istanza di stringa.

foo non contiene di per sé l'istanza della 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.

    
risposta data 29.06.2011 - 18:30
fonte

Leggi altre domande sui tag