2015-04-20 14 views
13

In Ruby weisen wir Objekten mit dem Operator Werte zu.Wie behandelt Ruby die Zuweisung semantisch?

Kombinieren Sie diese mit impliziter Typisierung und wir häufig Situationen wie diese:

myVar= :asymbol 

Die obige Zeile erzeugt sowohl ein neues Symbol-Objekt und bindet das Objekt an die Variablennamen myVar.

Semantisch, wie wird das gemacht?

Ich habe es mir in den Kopf gehämmert, dass der = Operator nicht Magie Syntax in den Interpreter eingebaut ist, ist aber eigentlich nur syntaktischer Zucker für die object.=(value) Methode.

In diesen Sinne, meine beste Vermutung ist, dass, wenn die Dolmetscher wir Wert auf einen nicht definierten Variablennamen zuweisen versuchen, sieht es zunächst ein neues Objekt von einer besonderen Art schafft, wie undefined oder null oder so etwas, und Übergibt dann die Nachricht := an dieses Objekt, wobei die Nutzlast der Wert ist, den wir zuweisen möchten.

jedoch Aufruf .class auf einem nicht instanzierte Objekt wirft nur eine Ausnahme, weil Rubin denkt wir versuchen, eine Methode aufrufen (dessen Name ist der Name der Variablen, die Sie versuchen, ins Leben zu bringen) auf self

Also, soweit ich das beurteilen kann, habe ich keine Möglichkeit, dies experimentell herauszufinden.


Randbemerkung:

Im Fall der Symbolzuordnung, glaube ich, dass der zugewiesene Wert (AKA der Wert durch das instanziiert Objekt zurückgegeben object_id Methode, AKA der Wert des unsigned long VALUE Variable auf dem C level) ist eine Zahl, die irgendwo einen Offset in einer Tabelle darstellt (ich glaube, so erreicht Ruby den 'unmittelbaren Wert' für Symbolobjekte).

In anderen Fällen kann der Wert eine direkte Codierung des Objekts selbst sein, oder ein Wert, der in einen Zeiger in Bezug auf eine struct umgewandelt werden soll.

Unabhängig davon, wie Ruby das Objekt darstellt und ob wir am Ende eine Referenz oder das Objekt selbst zuweisen, ist nicht das, worum ich hier bitte.

Zusätzliche Frage:

Welche Klasse ist die = Methode geerbt von? Ich kann es in der Spezifikation für Object oder BasicObject nicht finden.

+2

Wie "Es gibt keinen Löffel" gibt es keine '=' Methode. – tadman

+0

Ist das ein Duplikat dieser Frage? http://StackOverflow.com/Questions/8345755/Object-Assignment-in-Ruby –

+0

@GeorgeStocker Die referenzierte Frage ist über den ** Effekt ** des '=' -Operators, wobei sich bei mir um seine Implementierung in Ruby handelt. – LukeP

Antwort

13

Variablen sind im technischen Sinne nur Zeiger auf Objekte. Das ist nicht bemerkenswert, aber eine einfache Variablenzuweisung an ein vorhandenes Objekt erfordert keine Methodenaufrufe oder Nachrichten.

Remember-Variablen sind nur vorhanden, so dass Programmierer auf Objekte anhand des Namens verweisen können, anstatt auf irgendeine Art von internem Bezeichner oder Speicherplatz.Es gibt also ein bisschen "Magie", = ist etwas Besonderes, wenn man eine Aufgabe macht, denn es gibt Regeln für das, was man auf der linken und rechten Seite tun kann.

Der einzige Weg, wie Sie Nachrichten an etwas senden können, das sind Methodenaufrufe, ist, wenn Sie es auf eine Weise definiert haben, die der Compiler versteht. x = 1 ist ausreichend, es bedeutet x bezieht sich auf die Fixnum in Frage. Beachten Sie, dass der Ruby-Interpreter ermitteln muss, ob x auf einen Variablen- oder Methodenaufruf verweist, da x= eine Methode sein kann, die für den Objektkontext definiert ist, in dem dies ausgewertet wird.

Zum Beispiel:

class Example 
    def x=(value) 
    @x = value 
    end 

    def test 
    # Equivalent to send(:x=, 1) because x= is a method 
    x = 1 

    # Is a variable definition because y= is not a method 
    y = 2 

    # Is always a method call because self is referenced. 
    self.x = 3 
    end 
end 

# Is a variable definition because x= is not defined in this context 
x = 4 

Wenn es keine x= Methode für Ihr Objekt ist, wird x automatisch angenommen, eine Variable zu sein.

Sie können keine := Nachricht haben, weil das bedeuten würde, dass Sie ein Objekt durch ein anderes ersetzen können, was nicht erlaubt ist. Sobald ein Objekt erstellt wurde, kann es den Typ nicht magisch ändern. Dazu müssen Sie eine neue Instanz eines anderen Objekts erstellen. Variablen scheinen nur die Typen zu ändern, aber tatsächlich zeigen sie nur auf verschiedene Objekte.

Also kurz, es gibt keine := Methodenaufruf, aber es kann spezielle Methoden wie :x=, die in sehr spezifischen Fällen arbeiten.

+0

Gute Antwort! ... –

+1

Eine andere Sache: 'value =" newval "' wird immer als eine Variable (und nicht als eine Methode) angenommen, es sei denn, es gibt einen expliziten Empfänger. Wenn Ihr Kontext also ': value =' definiert hat, müssen Sie explizit 'self.value = arg' aufrufen, um auf diese Methode zuzugreifen. – acsmith

+0

@acsmith Dies wird zu einem Problem, wenn die Methode nach dem Kompilieren des Codes eingeführt wird. Guter Punkt. – tadman