Ändern des Werts von ruby-Variablen/Referenzen
Ich stolperte über etwas, was ich nicht ganz verstehen. Ich weiß, dass die Variablen in ruby sind Referenzen. So genial, dass Zeug ist möglich. Aber wenn ich übergeben Sie eine variable an eine Methode, es verhält sich seltsam:
my_var_a = "nothing happend to me"
my_var_b = "nothing happend to me"
def parse_set(my_var_set)
my_var_set = "my value changed"
end
def parse_sub(my_var_sub)
my_var_sub.sub! /(.*)/, "my value changed"
end
parse_set(my_var_a)
parse_sub(my_var_b)
my_var_a # => "nothing happend to me"
my_var_b # => "my value changed"
Können Sie mir erklären, warum es funktioniert mit sub!
und =
lässt das Objekt unverändert? Wie kann ich vermeiden, um sub!
aber mit dem gleichen Ergebnis?
Du musst angemeldet sein, um einen Kommentar abzugeben.
my_var_a
undmy_var_set
sind unterschiedliche Referenzen, aber Sie zeigen auf das gleiche Objekt. Wenn Sie das Objekt ändern inmy_var_set
, die änderung zeigt sich inmy_var_a
. Allerdings, wenn Sie repointmy_var_set
auf ein neues Objekt, das ändert nichts, wasmy_var_a
Punkte an.Edit: Klärung...
Was Ruby tut, ist aufgerufen, die übergabe von Referenzen von Wert. Wenn Sie sagen,
Ruby speichert den string "nothing happend to me" in einem Speicherplatz (sagen wir 1000), und speichert die
my_var_a
Referenz in einem anderen Speicher-Ort (sagen wir, 2000). Wenn Ihr code verwendetmy_var_a
, der interpreter sucht am Standort 2000, zu sehen, dass es Punkte auf 1000, dann wird der eigentliche string-Wert von 1000.Beim Aufruf
parse_set(my_var_a)
Ruby tatsächlich erstellt eine neue Referenz namensmy_var_set
und verweist auf die Zeichenfolge, diemy_var_a
war deutete auf (memory-Position 1000). Allerdingsmy_var_set
ist eine Kopie dermy_var_a
Referenz-sagen wirmy_var_set
wurde Speicheradresse 3000.my_var_a
undmy_var_set
sind 2 völlig verschiedene Referenzen im Speicher, Sie passieren einfach-Punkt in der gleichen genaue Position im Speicher hält, die die string-Wert.Die Aussage
my_var_set = "my value changed"
imparse_set
erstellt eine neue Zeichenfolge, die im Speicher und Punktemy_var_set
an, die neue memory location. Dies bedeutet jedoch nicht ändern, was die ursprünglichemy_var_a
Referenz Punkte an! Nun, dassmy_var_set
Punkte an eine andere Position im Speicher, nichts, was Sie tun, um diese variable beeinflussenmy_var_a
.Die gleiche Referenz kopieren passiert
parse_sub
als gut. Aber der Grund, dassparse_sub
Veränderungen der string ist, weil Sie den Aufruf der Methode direkt auf diemy_var_sub
Referenz. Wenn Sie dies tun, wird der interpreter bekommt das Objekt, dasmy_var_sub
gerichtet ist und dann ändert es. So dass der Wandel in dermy_var_a
Referenz, weil es noch Punkte auf die gleiche Zeichenfolge.parse
Methode einen Wert zurückgeben, und weisen Sie es auf die ursprüngliche variable:my_var_a = some_parse_method(my_var_a)
.Habe ich in Benutzung hatte
replace
genau null mal in all den Jahren, ich habe die Programmierung in Ruby. Ich Frage mich, ob es ein besseres design für Ihren code.Meisten string-Methoden, die sich ändern, die Empfänger werden mit dem Suffix ! (sub!, Kapital!, chomp!, etc.) Einige, ändern Sie den Empfänger nicht mit dem Suffix ! (ersetzen ist). Wenn Sie eine Methode aufrufen, die änderungen der Empfänger, und alle Verweise auf das Objekt wird die änderung sehen. wenn Sie eine Methode aufrufen, die sich nicht ändert-Empfänger, die Methode gibt eine neuen string.
gsub, ändert sich nicht der Empfänger, sondern liefert eine neue Instanz von String:
gsub! ändern Sie die Empfänger:
"Wie kann ich vermeiden, um sub! aber mit dem gleichen Ergebnis?"
Legen Sie es als eine Instanzvariable eines Objekts (obwohl dies funktioniert nur in Ihrem Haupt-Skript, ich empfehle das erstellen Ihrer eigenen Klasse, wenn Sie möchten, verwenden Sie die Instanz-Variablen-Ansatz).