Frage

Gibt es eine einfache Möglichkeit zu testen, ob ein Objekt eine unveränderlich (Zahlen, nil) oder nicht (Array, Hash, Objekte)? Mit anderen Worten, es könnte durch die Nebenwirkungen von anderem Code geändert werden?

Motivation: Ich will einen versioniert Wertspeicher schaffen, aber einige der Daten-Arrays. Einige der Arrays speichern benutzerdefinierte Objekte, und ich konnte die Beziehung umkehren, indem die ‚in‘ Eigenschaft zu speichern und die Suche nach ihm. Aber ich würde auch zum Speichern von Arrays von Symbolen in der Lage sein mag, andere Arrays, etc.

War es hilfreich?

Lösung

Es gibt keine primitiven Objekte in Ruby. Dies kann daher nicht auf einfache Weise erkannt werden.

Kann man einfach nicht Marshal oder YAML für Ihren versioniert Speicher verwenden? Dann werden Sie das Laden und Speichern aller Objekttypen kostenlos. Warum das Rad neu erfinden?

Ich weiß nicht, was Sie genau erreichen wollen, aber an der Quelle des YAML suche interessant sein zu sehen, wie sie dieses Problem umgehen. The Ruby YAML Codierung Implementierung einfach implementiert die to_yaml Methode für alle relevanten Klassen. Siehe yaml / rubytypes.rb .

Andere Tipps

Ich fand eine ineffiziente Art und Weise:

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

Die Idee der Veränderlichkeit nicht wirklich in Ruby gilt die gleiche Art und Weise wie in anderen Sprachen. Das einzige unveränderliche Objekt ist ein gefrorener ein. Sie können auch Methoden und Instanzvariablen Fixnums hinzuzufügen. Zum Beispiel:

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

Offensichtlich ist die überwiegende Mehrheit der Zeit, die Menschen gehen als pathologisch nicht genug Attribute Fixnum hinzuzufügen, aber der Punkt ist, kein nicht gefrorenes Objekt ist wirklich unveränderlich.

Wenn Sie mit einer cannonical Liste der Klassen kommen können, die Sie wollen, sind zu übernehmen unveränderlich, Sie könnten nur durchlaufen und geben ihnen alle eine immutable?() Methode, die true zurückgibt (und Objekt eine Version, die falsch zurückgibt). Aber wie wvanbergen sagte, der beste Weg, um Ihre Kopie eines Objekts um sicherzustellen, dass nicht ändern ist tief kopieren Sie ihn mit Marshal.

Ein weiterer Unterschied: native unveränderliche Objekte können nicht eingefroren werden, aber sie immer noch false zurück aus gefrorenen

5.freeze.frozen? == false

Einfrieren erhebt keine Ausnahme (im Gegensatz zu dup) aber es funktioniert (dauerhaft!) Ändert veränderbare Objekte.

Ich habe festgestellt, dass ich (zumindest in seinem gegenwärtigen Zustand) ordne meine app mit gefrorenen Objekten zu arbeiten, und Rubin gibt mir eine Ausnahme, wenn ich versuche, sie direkt zu ändern. Allerdings einfrieren wirkt sich nur auf die erste Ebene des Objekts und Arrays, usw. gespeichert in noch geändert werden kann.

Dies gilt nur für 1.8 - 5.frozen? kehrt in ruby1.9 (aber nicht in irb1.9)

true
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top