2009-05-26 17 views
8

Mi chiedo come viene definita l'immutabilità? Se i valori non sono esposti come pubblici, quindi non possono essere modificati, è sufficiente?La vera definizione di immutabilità?

I valori possono essere modificati all'interno del tipo, non dal cliente del tipo?

Oppure è possibile impostarli solo all'interno di un costruttore? Se è così, nei casi di doppia inizializzazione (usando la parola chiave this su struct, etc) è ancora ok per i tipi immutabili?

Come posso garantire che il tipo sia immutabile al 100%?

risposta

23

Se i valori non sono esposti come pubblici, quindi non possono essere modificati, è sufficiente?

No, perché è necessario l'accesso in lettura.

I valori possono essere modificati all'interno del tipo, non dal cliente del tipo?

No, perché è ancora una mutazione.

Oppure è possibile impostarli solo all'interno di un costruttore?

Ding ding ding! Con il punto aggiuntivo che i tipi immutabili spesso hanno metodi che costruiscono e restituiscono nuove istanze e spesso hanno anche costruttori extra contrassegnati con internal appositamente per l'uso con tali metodi.

Come posso garantire che il tipo sia immutabile al 100%?

In .Net è difficile ottenere una garanzia come questa, perché è possibile utilizzare la riflessione per modificare (mutare) membri privati.

+2

Quasi tutto copre ;-p –

+0

Ehi Marc, sono sorpreso di non vederti sulle mie recenti domande immutabili. Immutabilità mi ricorda di te :) –

3

Qui è la definizione di immutabilità da Wikipedia (link)

"In orientata agli oggetti e programmazione funzionale, un oggetto immutabile è un oggetto il cui stato non può essere modificato dopo la creazione."

In sostanza, una volta creato l'oggetto, nessuna delle sue proprietà può essere modificata. Un esempio è la classe String. Una volta creato un oggetto String, non può essere modificato. Qualsiasi operazione eseguita su di esso crea effettivamente un nuovo oggetto String.

1

Ho imparato che l'immutabilità è quando si imposta tutto nel costruttore e non è possibile modificarlo in un secondo momento durante la vita dell'oggetto.

1

La definizione di immutabilità può trovarsi su Google.

Esempio:

immutabili - letteralmente, non è in grado di cambiare.
www.filosofia.net/materiales/rec/glosaen.htm

In termini di strutture di dati immutabili, la definizione tipica è write-once-read-many, in altre parole, come dici tu, una volta creata, non può essere modificata.

Ci sono alcuni casi che sono leggermente nell'area grigia. Ad esempio, le stringhe .NET sono considerate immutabili, poiché non possono essere modificate, tuttavia, StringBuilder modifica internamente un oggetto String.

1

Un'immutabile è essenzialmente una classe che si impone di essere definitiva all'interno del proprio codice. Una volta lì, nulla può essere cambiato. A mia conoscenza, le cose sono impostate nel costruttore e poi è tutto. Non vedo come qualcosa potrebbe essere immutabile altrimenti.

3

Un sacco di domande lì. Proverò a rispondere a ciascuno di essi individualmente:

  • "Mi chiedo come viene definita l'immutabilità?" - Direttamente dal Wikipedia page (e perfettamente accurata definizione/sintetica)

    Un oggetto immutabile è un oggetto il cui stato non può essere modificato dopo la creazione

  • "Se i valori non sono esposti come pubblico, quindi non può essere modificato, quindi è abbastanza? " - Non proprio. Non può essere modificato in in qualsiasi modo, quindi è necessario assicurarsi che metodi/funzioni non cambino lo stato dell'oggetto e, se si eseguono operazioni, restituire sempre una nuova istanza.

  • "I valori possono essere modificati all'interno del tipo, non dal cliente del tipo?" - Tecnicamente, non può essere modificato né all'interno né da un consumatore del tipo. In pratica esistono tipi come System.String (un tipo di riferimento per la materia) che può essere considerato mutabile per quasi tutti gli scopi pratici, sebbene non in teoria.

  • "Oppure è possibile impostarli solo all'interno di un costruttore?" - Sì, in teoria è il solo luogo in cui è possibile impostare lo stato (variabili).

  • "Se è così, nei casi di doppia inizializzazione (utilizzando questa parola chiave su struct, etc) è ancora ok per i tipi immutabili?" - Sì, è ancora perfettamente funzionante, perché fa tutto parte del processo di inizializzazione (creazione) e l'istanza non viene restituita finché non è terminata.

  • "Come posso garantire che il tipo sia immutabile al 100%?" - Le seguenti condizioni dovrebbero assicurarlo. (Qualcuno si prega di indicare se ne manchi uno.)

    1. Non esporre alcuna variabile. Dovrebbero essere tutti mantenuti private (nemmeno protected è accettabile, poiché le classi derivate possono quindi modificare lo stato).
    2. Non consentire a qualsiasi metodo di istanza di modificare lo stato (variabili). Questo dovrebbe essere fatto solo nel costruttore, mentre i metodi dovrebbero creare nuove istanze usando un particolare costruttore se richiedono di restituire un oggetto "modificato".
    3. Tutti i membri esposti (come di sola lettura) o gli oggetti restituiti dai metodi devono essere immutabili.

    Nota: non è possibile assicurare l'immutabilità dei tipi derivati, poiché possono definire nuove variabili. Questo è un motivo per contrassegnare qualsiasi tipo che non vuoi rendere immutabile come sealed in modo che nessuna classe derivata possa essere considerata del tuo tipo immutabile di base ovunque nel codice.

Spero che questo aiuti.

+1

Vorrei aggiungere che, se esponi membri, probabilmente dovrebbero anche essere immutabili ... –

+0

@Denis: Sì, sapevo che mi mancava qualcosa di ovvio. Grazie! – Noldorin

+0

Grazie. Cosa succede se qualcuno avvolge la mia classe immutabile per fare un tipo immutabile? Come dire che esponi point.X, point.Y per la lettura e lui li usa per riflettere/aggiornare i cambiamenti? Qualcuno mi ha detto che le persone addirittura ignorano le classi sigillate. –

7

I poster precedenti hanno già dichiarato che è necessario assegnare valori ai campi nel costruttore e quindi tenere le mani lontane. Ma a volte ciò è più facile a dirsi che a farsi. Diciamo che il tuo oggetto immutabile espone una proprietà del tipo List<string>. L'elenco è autorizzato a cambiare? E se no, come lo controllerai?

Eric Lippert ha scritto una serie di post nel suo blog sull'immutabilità in C# che potresti trovare interessante: you find the first part here.

+0

Questa è una domanda interessante. Puoi rendere la lista di sola lettura? –

+4

Dipende dal tipo esatto che esponi. Con un elenco non è possibile, ma se si esporre un ReadOnlyCollection si potrebbe (non so abbastanza su di esso per affermare che è garantito di essere di sola lettura). Ma anche gli array regolari sono mutabili, quindi è davvero necessario prestare attenzione a quali tipi si espongono in un tipo immutabile. –

+0

+1 per il collegamento Mr. Lippert: P – Lucas

5

Una cosa che penso possa mancare in tutte queste risposte è che penso che un oggetto possa essere considerato immutabile anche se il suo stato interno cambia, purché tali modifiche interne non siano visibili al codice "client".

Ad esempio, la classe System.String è immutabile, ma penso che sarebbe consentito memorizzare nella cache il codice hash per un'istanza, in modo che l'hash venga calcolato solo alla prima chiamata a GetHashCode(). Si noti che, per quanto ne so, la classe System.String fa non fare questo, ma penso che possa e sia ancora considerato immutabile. Naturalmente qualsiasi di questi cambiamenti dovrebbe essere gestito in modo thread-safe (in linea con l'aspetto non osservabile dei cambiamenti).

Per essere onesti, però, non riesco a pensare a molte ragioni per cui si potrebbe desiderare o che si necessita di questo tipo di "mutevolezza invisibile".

+0

Buon punto Michael. –

+2

Un esempio: alberi splay. La mutazione interna è usata puramente per migliorare le prestazioni della ricerca, ma il codice client non può dire che è avvenuta una mutazione (Naturalmente, è anche possibile l'implementazione mutabile di splay tree) –

+0

Confronta la parola chiave C++ "mutable", che designa un membro della classe che può essere cambiato anche in un'operazione const. Questo di solito è per motivi di prestazioni, supportando la valutazione pigra di qualcosa o altro. –

1

Non ci sono purtroppo parole chiave immutabili in C#/vb.net, anche se è stato discusso, ma se non ci sono autoproprietà e tutti i campi sono dichiarati con readonly (i campi readonly possono solo essere assegnati nel costruttore) modfier e che tutti i campi sono dichiarati di un tipo immutabile, tu avrai assicurato la tua immutabilità.

1

Un oggetto immutabile è uno il cui stato osservabile non può mai essere modificato da alcuna sequenza plausibile di esecuzione del codice. Un tipo immutabile è quello che garantisce che le istanze esposte al mondo esterno siano immutabili (questo requisito viene spesso indicato come richiedendo che lo stato dell'oggetto possa essere impostato solo nel suo costruttore, questo non è strettamente necessario nel caso di oggetti con costruttori privati, né è sufficiente nel caso di oggetti che chiamano metodi esterni su se stessi durante la costruzione).

Un punto che altre risposte hanno trascurato, tuttavia, è una definizione dello stato di un oggetto. Se Foo è una classe, lo stato di List<Foo> consiste nella sequenza di identità di oggetto in esso contenuta. Se l'unico riferimento a una particolare istanza List<Foo> è detenuto da un codice che non causerà la modifica di tale sequenza, né la esporrà al codice che potrebbe farlo, quell'istanza sarà immutabile, indipendentemente dal fatto che gli oggetti Foo in esso menzionati siano mutevole o immutabile.

Per utilizzare un'analogia, se si dispone di un elenco di VIN automobilistici (numeri di identificazione del veicolo) stampati su carta a prova di manomissione, la lista stessa sarebbe immutabile anche se le auto non lo sono.Anche se la lista contiene dieci macchine rosse oggi, potrebbe contenere dieci macchine blu domani; sarebbero comunque le stesse dieci automobili.

Problemi correlati