2012-03-24 15 views
1

Vielleicht weiß ich einfach nicht genug über Strukturen und habe sie blind verwendet, aber das Ergebnis unten erscheint mir irrational.Warum verschwindet diese Variable in einer Struktur?

class VarTest < Struct.new(:email) 
    def perform 
    puts "Start: #{email}" 
    if email == "nothing" 
     email = "bad email" 
    end 
    puts "End: #{email}" 
    end 
end 
VarTest.new("[email protected]").perform 

unerwartete Ausgang:

Start: [email protected] 
End: 

Wenn ich ändern Sie den Code an:

class VarTest < Struct.new(:email) 
    def perform 
    e = email 
    puts "Start: #{e}" 
    if e == "nothing" 
     e = "bad email" 
    end 
    puts "End: #{e}" 
    end 
end 

VarTest.new("[email protected]").perform 

Wir erhalten die erwartete Ausgabe:

Start: [email protected] 
End: [email protected] 

Kann mir bitte jemand erklären, was hier vor sich geht?

Danke.

+0

Was ist das eigentliche Ziel? Mit anderen Worten, warum verwenden Sie Vererbung anstatt nur 'VarTest = Struct.new (: email)' dann 'VarTest.new ('[email protected]')'? –

+0

Es wird von verzögerter Arbeit als Teil der Enqueue verwendet. Egal, warum verursacht dieses Verhalten dieses Verhalten? – chrishomer

Antwort

4

Wenn Sie email = "bad email" durch self.email = "bad email" ersetzen, funktioniert es wie erwartet. Dies gilt immer, wenn Sie Setter verwenden.

Der Grund ist einfach: Wenn Ruby auf ein Bareword stößt, versucht es, es als eine lokale Variable aufzulösen. Wenn keine vorhanden ist, wird versucht, eine Methode mit diesem Namen aufzurufen. Innerhalb des Klassenkörpers ist das Selbst der implizite Empfänger, also arbeiten die Leser einfach. Jetzt für den Schreiber gibt es ein Problem. Wenn Sie etwas wie foo = "bar" schreiben, erstellt Ruby eine neue lokale Variable, daher müssen Sie den Empfänger explizit machen.

Dieser Fall ist ein wenig komplizierter: if email == "nothing" verwendet den Getter. email = "bad email" wird jedoch weiterhin vom Parser erkannt und eine lokale Variable email wird auf nil gesetzt. Dies geschieht immer dann, wenn der Parser ein Bareword als LHS einer Zuweisung sieht. Dieser lokale Wert nil ist, was es scheint, wie der Wert email verschwindet (das können Sie überprüfen, indem Sie nur die letzte puts zu puts "End: #{self.email}" ändern).

+0

genial. Das ist also nicht nur in Structs möglich. Ich wusste nicht, dass Struct-Variablen so funktionierten. Macht im Nachhinein perfekten Sinn. Nun, das Lernen geht weiter und das macht das Zeug lustig! Vielen Dank! – chrishomer

Verwandte Themen