[Ruby] Gewöhnen Sie sich an, beim Erstellen einer Kopie einer Zeichenfolgenvariablen die dup-Methode zu verwenden

Vorwort

Ich programmiere in Ruby und bin süchtig danach oder süchtig danach, also vergiss nicht.

Umgebung

Vorerst auch Versionsinformationen. Aber es ist einfach, also sollte es keine Rolle spielen.

Wenn Sie eine Kopie des Werts einer Variablen erstellen ...

Wenn Sie eine Kopie des Werts einer Variablen erstellen, müssen Sie nur eine Zuweisung vornehmen?

@bob = "I love you"
@carol = @bob         # <=Hier!

puts "@bob = #{@bob}, @carol = #{@carol} "
    # => @bob = I love you, @carol = I love you

Wenn Sie eine Kopie des Werts einer Variablen erstellen, haben Sie normalerweise den Zweck, "den Wert der ursprünglichen Variablen beizubehalten und die kopierte Variable für verschiedene Operationen zu verwenden". Selbst wenn sich der Wert der kopierten Variablen ändert und sie bricht, ist dies in Ordnung, da die ursprüngliche Variable gespeichert wird.

# ---Fortsetzung oben---
@carol = @carol + ", too"
puts "@bob = #{@bob}, @carol = #{@carol} "
    # => @bob = I love you, @carol = I love you, too

Wie oben gezeigt, ändert sich der Wert der Zuweisungsquellvariablen "@ bob" nicht, selbst wenn Sie der Zeichenfolge zur Zuweisungszielvariablen "@ carol" hinzufügen ~~ Natürlich ~~.

Wenn Sie jedoch eine "destruktive Operation" ausführen, z. B. das Ersetzen der Zeichenfolge in der Zuweisungszielvariablen, wird auch der Wert der Zuweisungsquelle beeinflusst.

@bob = "I love you"
@carol = @bob

@carol.sub!("love", "hate")

puts "@bob = #{@bob}, @carol = #{@carol} "
    # => @bob = I hate you, @carol = I hate you

Ich hätte den Wert von "@ carol" ändern sollen, aber der Wert von "@ bob" hat sich auch geändert.

Der Grund dafür ist, dass in Ruby alles ein Objekt ist und der Zuweisungsoperator "als Referenz übergeben" wird, um das ~~ Referenzziel ~~ zu kopieren und die Objektreferenz zu kopieren. [^ 1] Wenn @carol = @ bob, dann beziehen sich @ carol und @ bob auf dasselbe String-Objekt. Wenn Sie also eine "destruktive Operation" auf der "@ carol" -Seite ausführen, ändern sich beide, da das Objekt, auf das "@ bob" verweist, dasselbe ist.

Übrigens ändert sich das Verhalten auch bei derselben Operation erneut, wenn Sie sie mit der Methode "sub" anstelle von "sub!" Ändern.

# ---Fortsetzung oben---
@bob = @bob.sub("hate", "love")                                                

puts "@bob = #{@bob}, @carol = #{@carol} "                                     
    # => @bob = I love you, @carol = I hate you

Ich habe die Saite "@ bob" auf die gleiche Weise in "love" geändert, aber "@ carol" ist immer noch "Hass". .. .. Ich habe dich gehasst, Bob. .. ..

Aber wieso?

Im Fall von "sub!" Wird der Inhalt dieses Objekts direkt geändert, im Fall von "sub" wird die ersetzte Zeichenfolge "als neues Objekt generiert" und erneut "@ bob" zugewiesen. Weil es gibt. Das referenzierte Objekt wurde von dem mit @ carol referenzierten Objekt in ein neues geändert.

Aus dem gleichen Grund hat im ersten Beispiel das Hinzufügen von "too" zur Zeichenfolge "@ carol" den Wert von "@ bob" nicht geändert. Durch Hinzufügen einer weiteren Zeichenfolge zur Zeichenfolge von "@ carol" wurde ein "neues Objekt" der kombinierten Zeichenfolge erstellt und "@ carol" zugewiesen, sodass es als "@bob" bezeichnet wird. Dies liegt daran, dass sich das Objekt geändert hat.

Auf diese Weise kann sich der Wert der Zuweisungsquelle abhängig von der nachfolgenden Verarbeitung ändern, wenn Sie erleichtert sind zu glauben, dass Sie den Wert einfach durch Zuweisung kopiert haben, aber je nach Verarbeitungsreihenfolge kann er in Ordnung sein. Wird passieren.

Was machst du dann?

Wie ich bereits geschrieben habe, möchten Sie eine Variable kopieren, weil Sie den Wert der Kopierquelle speichern möchten. Ich gehe daher nicht davon aus, dass sich auch der Wert der Kopierquelle ändert, wenn Sie den Wert des Kopierziels ändern. Es ist eine schlechte Idee. Sie müssen es nicht kopieren, wenn Sie es ändern können.

Was soll ich dann tun?

Deshalb kommt die "dup" -Methode heraus. Die "dup" -Methode ist eine Methode zum Duplizieren eines Objekts, dh zum Erstellen eines anderen Objekts mit demselben Inhalt.

@bob = "I love you"
@carol = @bob.dup      # <==Hier in der Dup-Methode@Erstellen Sie ein neues Objekt, das den Wert von bob kopiert, und weisen Sie ihn zu

@carol.sub!("love", "hate")

puts "@bob = #{@bob}, @carol = #{@carol} "
    # => @bob = I love you, @carol = I hate you

Es sieht genauso aus, aber dieses Mal hat sich nur "@ carol" in "Hass" geändert. Immerhin wird Bob gehasst. .. .. Dies liegt daran, dass sich das mit der Methode "dup" erstellte Objekt von dem Objekt unterscheidet, das "@ bob" hat.

Sie können die Methode "object_id" verwenden, um festzustellen, ob die Objekte übereinstimmen.

@bob = "I love you"
@carol = @bob
puts @bob.object_id    # => 46779560
puts @carol.object_id  # => 46779560

@anna = @bob.dup
@anna.object_id        # => 46931780

Wenn Sie es so zuweisen, wie es ist, hat es dieselbe Objekt-ID, und wenn Sie es mit der Methode "dup" erstellen, hat es natürlich eine andere Objekt-ID.

Auf diese Weise handelt es sich auch bei gleichem Wert um ein völlig anderes Objekt. Unabhängig davon, wie Sie damit spielen, ändert sich der ursprüngliche Wert nicht ohne Erlaubnis.

Tatsächlich denke ich, dass es viele Fälle gibt, in denen es kein Problem gibt, nur "zuzuweisen", weil sich das Objekt in der nachfolgenden Operation ändert. Es besteht jedoch ein hohes Risiko, Fehler zu verursachen, wenn Sie diese versehentlich beeinflussen. Damit

Wenn Sie Variablen kopieren, weisen Sie sie nicht zu, verwenden Sie die dup-Methode oder etwas anderes, um sie richtig zu duplizieren

Ich werde mein Bestes geben, damit ich Dinge unbewusst tun kann (ich sage mir ...)

Und dazu ...

Zusätzlich zur "dup" -Methode gibt es eine "Klon" -Methode zum Replizieren von Objekten. Sie können auch "marshal_dump", "marshal_load" verwenden.

Für die Vervielfältigung von String-Objekten ist "dup" ausreichend. Zusätzlich zu "dup" dupliziert "clone" auch eine Kopie der singulären Methode und des eingefrorenen Zustands des Objekts. Beim Duplizieren eines Arrays, Hashs oder einer Klasse dupliziert dup oder clone keine Elemente oder internen Variablen, was nicht ausreichend ist. In diesem Fall müssen Sie "marshal_dump", "marshal_load" verwenden und die Methode bei Bedarf überschreiben.

Bitte überprüfen Sie die detaillierte Geschichte hier. (Ich muss auch lernen ...)

[^ 1]: Das Wort "Referenzübergabe" wurde gelöscht.

Recommended Posts