Domanda

Esiste un modo semplice per verificare se un oggetto è immutabile (numeri, zero) o no (matrice, hash, oggetti)? In altre parole, potrebbe essere modificato dagli effetti collaterali di altri codici?

Motivazione: voglio creare un archivio valori con versione, ma alcuni dei dati sono array. Alcuni array memorizzeranno oggetti personalizzati e potrei invertire la relazione memorizzando la proprietà 'in' e cercandola. Ma vorrei anche essere in grado di memorizzare matrici di simboli, altre matrici, ecc.

È stato utile?

Soluzione

Non ci sono oggetti primitivi in ??Ruby. Questo non può quindi essere rilevato in modo semplice.

Non puoi semplicemente usare Marshal o YAML per il tuo negozio con versione? Quindi otterrai il caricamento e il salvataggio di tutti i tipi di oggetti gratuitamente. Perché reinventare la ruota?

Non so esattamente cosa vuoi ottenere, ma guardare la fonte di YAML può essere interessante per vedere come gestiscono questo problema. L'implementazione della codifica YAML di Ruby implementa semplicemente il metodo to_yaml per tutte le classi pertinenti. Vedi yaml / rubyty. .

Altri suggerimenti

Ho trovato un modo inefficiente:

class Object
  def primitive?
    begin
      self.dup
      false
    rescue TypeError
      true
    end
  end
end

L'idea della mutabilità in realtà non si applica in Ruby allo stesso modo di in altre lingue. L'unico oggetto immutabile è un oggetto congelato. È anche possibile aggiungere metodi e variabili di istanza a Fixnums. Ad esempio:

class Fixnum
  attr_accessor :name
end
1.name = "one"
2.name = "two"

Ovviamente, la stragrande maggioranza delle volte, le persone non saranno abbastanza patologiche per aggiungere attributi a Fixnum, ma il punto è che nessun oggetto non congelato è veramente immutabile.

Se riesci a trovare un elenco cannonico di classi che vuoi assumere immutabili, potresti semplicemente passare attraverso e dare a tutti loro un metodo immutabile? () che restituisce true (e Object una versione che restituisce false). Ma come ha detto wvanbergen, il modo migliore per assicurarsi che la tua copia di un oggetto non cambi è quello di copiarlo in profondità con il Maresciallo.

Un'altra differenza: gli oggetti nativamente immutabili non possono essere congelati, ma restituiscono comunque false da congelati?

5.freeze.frozen? == false

Il blocco non genera un'eccezione (a differenza di dup) Tuttavia (permanentemente!) modifica gli oggetti mutabili.

Ho scoperto che posso (almeno nel suo stato attuale) organizzare la mia app affinché funzioni con oggetti congelati e ruby ??mi darà un'eccezione se provo a modificarli direttamente. Tuttavia il congelamento influisce solo sul primo livello dell'oggetto e le matrici, ecc. Memorizzate in esso possono ancora essere modificate.

Questo vale solo per 1.8 - 5. congelati? ritorna vero in ruby1.9 (ma non in irb1.9)

scroll top