Die Ruby-Dokumentedup
sagen zum Beispiel:
Im Allgemeinen
clone
unddup
kann unterschiedliche Semantik in absteigenden Klassen haben. Währendclone
zum Duplizieren eines Objekts einschließlich seines internen Status verwendet wird, wirddup
normalerweise die Klasse des untergeordneten Objekts zum Erstellen der neuen Instanz verwendet.
Aber als ich einen Test machte, stellte ich fest, dass sie tatsächlich gleich sind:
class Test
attr_accessor :x
end
x = Test.new
x.x = 7
y = x.dup
z = x.clone
y.x => 7
z.x => 7
Was sind also die Unterschiede zwischen den beiden Methoden?
dup
und wasclone
, sondern auch, warum Sie das eine anstelle des anderen verwenden würden.Antworten:
Unterklassen können diese Methoden überschreiben, um unterschiedliche Semantiken bereitzustellen. An
Object
sich gibt es zwei wesentliche Unterschiede.Zuerst
clone
kopiert die Singleton - Klasse, währenddup
dies nicht tut.Zweitens
clone
bleibt der gefrorene Zustand erhalten, währenddup
dies nicht der Fall ist.Die Rubinius-Implementierung für diese Methoden ist oft meine Quelle für Antworten auf diese Fragen, da sie ziemlich klar ist und eine ziemlich konforme Ruby-Implementierung darstellt.
quelle
o = Object.new; class << o; A=5; end; puts ( class << o.clone; A; end ); puts ( class << o.dup; A; end )
.extend
für das ursprüngliche Objekt bearbeitet wurden. SoObject.new.extend(Enumerable).dup.is_a?(Enumerable)
gibt false zurück.Beim Umgang mit ActiveRecord gibt es auch einen signifikanten Unterschied:
dup
Erstellt ein neues Objekt, ohne dass seine ID festgelegt ist. Sie können also ein neues Objekt in der Datenbank speichern, indem Sie auf klicken.save
clone
Erstellt ein neues Objekt mit derselben ID, sodass alle an diesem neuen Objekt vorgenommenen Änderungen den ursprünglichen Datensatz überschreiben, wenn sie getroffen werden.save
quelle
dup
undclone
Methoden verwende, erhalteActiveRecord
ich umgekehrte Ergebnisse von dem, was Sie in der Antwort erwähnt haben. Das heißt, wenn ich es verwendedup
, erstellt es ein neues Objektid
, währendclone
es festgelegt wird, und während der Verwendung wird ein Objekt erstellt, ohne dass esid
festgelegt wird. Kannst du es bitte noch einmal untersuchen und klären? . Thnxclone
neuer Datensatz, der noch nie gespeichert wurde, sollte dann aber ziemlich sicher sein? Kann ich auf diese Weise ein "Vorlagenobjekt" erstellen und klonen, um bestimmte Instanzen zu speichern?Ein Unterschied besteht bei gefrorenen Objekten. Das
clone
eines eingefrorenen Objekts wird ebenfalls eingefroren (während dasdup
eines eingefrorenen Objekts nicht eingefroren ist).Ein weiterer Unterschied besteht bei Singleton-Methoden. Dieselbe Geschichte hier,
dup
kopiert diese nicht,clone
tut es aber .quelle
Beide sind fast identisch, aber der Klon macht eine Sache mehr als dup. Beim Klonen wird auch der eingefrorene Zustand des Objekts kopiert. In dup wird es immer aufgetaut.
quelle
Das neuere Dokument enthält ein gutes Beispiel:
quelle
Sie können Clone verwenden, um prototypbasierte Programmierung in Ruby durchzuführen. Die Ruby-Objektklasse definiert sowohl die Klonmethode als auch die Dup-Methode. Sowohl Klon als auch Dup erzeugen eine flache Kopie des Objekts, das kopiert wird. Das heißt, die Instanzvariablen des Objekts werden kopiert, nicht jedoch die Objekte, auf die sie verweisen. Ich werde ein Beispiel zeigen:
Beachten Sie im obigen Beispiel, dass der orangefarbene Klon den Status (dh die Instanzvariablen) des Apple-Objekts kopiert. Wenn das Apple-Objekt jedoch auf andere Objekte (z. B. die String-Objektfarbe) verweist, werden diese Verweise nicht kopiert. Stattdessen verweisen Apfel und Orange auf dasselbe Objekt! In unserem Beispiel ist die Referenz das Zeichenfolgenobjekt 'rot'. Wenn Orange die Append-Methode << verwendet, um das vorhandene String-Objekt zu ändern, ändert es das String-Objekt in 'red orange'. Dies ändert in der Tat auch apple.color, da beide auf dasselbe String-Objekt zeigen.
Als Randnotiz weist der Zuweisungsoperator = ein neues Objekt zu und zerstört so eine Referenz. Hier ist eine Demonstration:
Wenn wir im obigen Beispiel der Farbinstanzmethode des orangefarbenen Klons ein neues Objekt zugewiesen haben, verweist es nicht mehr auf dasselbe Objekt wie Apple. Daher können wir jetzt die Farbmethode von Orange ändern, ohne die Farbmethode von Apple zu beeinflussen. Wenn wir jedoch ein anderes Objekt von Apple klonen, verweist dieses neue Objekt auf dieselben Objekte in kopierten Instanzvariablen wie Apple.
dup erstellt auch eine flache Kopie des Objekts, das kopiert wird. Wenn Sie dieselbe Demonstration wie oben für dup ausführen, sehen Sie, dass dies genauso funktioniert. Es gibt jedoch zwei Hauptunterschiede zwischen Klon und Dup. Erstens kopiert der Klon, wie andere bereits erwähnt haben, den eingefrorenen Zustand und dup nicht. Was bedeutet das? Der Begriff "eingefroren" in Ruby ist ein esoterischer Begriff für unveränderlich, der selbst eine Nomenklatur in der Informatik ist, was bedeutet, dass etwas nicht geändert werden kann. Daher kann ein eingefrorenes Objekt in Ruby in keiner Weise geändert werden. es ist praktisch unveränderlich. Wenn Sie versuchen, ein eingefrorenes Objekt zu ändern, löst Ruby eine RuntimeError-Ausnahme aus. Da der Klon den eingefrorenen Status kopiert, wird beim Versuch, ein geklontes Objekt zu ändern, eine RuntimeError-Ausnahme ausgelöst. Umgekehrt, da dup den eingefrorenen Zustand nicht kopiert,
Zweitens und interessanterweise kopiert der Klon die Singleton-Klasse (und damit ihre Methoden)! Dies ist sehr nützlich, wenn Sie eine prototypbasierte Programmierung in Ruby durchführen möchten. Lassen Sie uns zunächst zeigen, dass die Singleton-Methoden tatsächlich mit dem Klon kopiert werden, und dann können wir sie in einem Beispiel für die prototypbasierte Programmierung in Ruby anwenden.
Wie Sie sehen können, wird die Singleton-Klasse der Fruchtobjektinstanz in den Klon kopiert. Und daher hat das geklonte Objekt Zugriff auf die Singleton-Methode: seeded?. Dies ist jedoch bei dup nicht der Fall:
In der prototypbasierten Programmierung gibt es jetzt keine Klassen, die andere Klassen erweitern und dann Instanzen von Klassen erstellen, deren Methoden von einer übergeordneten Klasse abgeleitet sind, die als Blaupause dient. Stattdessen haben Sie ein Basisobjekt und erstellen dann ein neues Objekt aus dem Objekt, dessen Methoden und Status kopiert wurden (da wir flache Kopien per Klon erstellen, werden natürlich alle Objekte, auf die die Instanzvariablen verweisen, wie in JavaScript freigegeben Prototypen). Sie können dann den Status des Objekts ausfüllen oder ändern, indem Sie die Details der geklonten Methoden eingeben. Im folgenden Beispiel haben wir ein Basisobstobjekt. Alle Früchte haben Samen, also erstellen wir eine Methode number_of_seeds. Aber Äpfel haben einen Samen, und so erstellen wir einen Klon und füllen die Details aus. Wenn wir jetzt Apfel klonen, haben wir nicht nur die Methoden geklont, sondern auch den Staat! Denken Sie daran, dass der Klon eine flache Kopie des Status erstellt (Instanzvariablen). Und aus diesem Grund hat red_apple automatisch 1 Samen, wenn wir Apfel klonen, um einen red_apple zu erhalten! Sie können sich red_apple als ein Objekt vorstellen, das von Apple erbt, das wiederum von Fruit erbt. Deshalb habe ich Obst und Apfel groß geschrieben. Wir haben die Unterscheidung zwischen Klassen und Objekten dank des Klons aufgehoben.
Natürlich können wir eine Konstruktormethode in der protoype-basierten Programmierung haben:
Letztendlich können Sie mit Klon etwas Ähnliches wie das Verhalten des JavaScript-Prototyps erhalten.
quelle