2016-06-22 9 views
2

Kann jemand erklären, warum dies "gute Nacht" druckt? Wenn Sie entferntMuting Objekte in Ruby

string = "hello" 

Es würde "gute Nacht Welt" drucken.

def a_method(string) 
    string = "hello" 
    string << " world" 
end 

bedtime = "goodnight" 
a_method(bedtime) 

puts bedtime 

Ich verstehe, dass < < mutiert, aber nicht, warum das Hinzufügen der = hallo macht einen so großen Unterschied?

+2

Da Ruby ist pass-by-Wert. Die Methode 'a_method' mutiert also nicht den ursprünglichen Verweis auf die Zeichenfolge' "goodnight" ' – user1875195

+1

In Ihrem Fall kommt es auf Ihre Verwendung von' '' '' an, die das Objekt ändert, anstatt nur eine geänderte Version zurückzugeben. Wenn Ihre Methode stattdessen "string +" world "hätte, würde das nicht passieren. –

+0

@ user1875195 Wenn 'a_method' nicht den ursprünglichen Verweis auf den String '' goodnight '' mutierte, dann würde ''goodnight world' 'nicht gedruckt. Die Verkettung von "Welt" mit "Schlafenszeit" mutiert es. –

Antwort

3

In Ruby gibt es einen Unterschied zwischen In-Place Operationen und diejenigen, die eine Kopie zurückgeben. Manchmal gibt der Name einen Hinweis, wie gsub vs gsub!, aber andere Zeiten müssen Sie nur wissen, wie <<.

Was Sie hier tun, ist neu definiert, welches Objekt string Referenzen, so dass keine dauerhafte Änderung an der ursprünglichen Referenz vorgenommen wird.

Die Zeile string = "hello" bedeutet nicht, dass sich der ursprüngliche Objektverweis bedtime ändert.

Wenn Sie diesen Effekt wollten, würden Sie string.replace("hello") tun, die eine In-Place-Neuzuweisung des Inhalts der Zeichenfolge ist.

Um herauszufinden, auf welches Objekt Sie verweisen, rufen Sie object_id auf dem Objekt in Frage. Sie werden hier feststellen, dass sich mit Ihrem Code dieser Wert ändert, aber mit replace nicht.

Ruby-Methode Argumente werden von Objektreferenz übergeben, die in der Praxis viel wie ein Zeiger ist. Wenn Sie erwarten, dass dieser Wert von absoluter Referenz übergeben wird, ist dies nicht der Fall.

+0

Vielen Dank @tadman, die eine Tonne hilft. –

+0

Diese Art von bläst meine Meinung. Woher weiß man, ob eine gegebene Methode eine "In-Place" -Operation ist? Außerdem schreibe ich ein Codebeispiel wie das in der Frage. –

+0

@Mike Es ist oft notwendig, die Dokumentation zu lesen und sich die Beschreibung genau anzusehen. ['Array # push'] (http://ruby-doc.org/core-2.3.0/Array.html#method-i-push) modifiziert in-place, viele der Array-Methoden verzichten auf einen Hinweis wie' ! 'vermutlich aufgrund der Tradition, es verhält sich genauso wie JavaScript, Python und andere. Andere Klassen sind expliziter über ihre Absicht, wie String mit 'gsub' vs.' gsub! '. Bis Sie sicher sind, lesen Sie die zu überprüfende Dokumentation. – tadman

Verwandte Themen