2009-12-16 4 views
5

diesen Java-Code wird angenommen:Beispiel Hilfe bei Scala Variablen benötigt

public class A { 
    public A(String g) { 
     x += g.length(); 
    } 

    private int x = 0; 
} 

Wenn ich eine Instanz von A, wie dies zu erstellen:

A a = new A("geo"); 

nach diesem Aufruf wird der Wert von x 3. Was mache ich falsch in meinem Scala-Code?

class A(val g:String) { 
    x += g.length 
    var x:Int = 0 
} 

object x extends Application { 
    val x = new A("geo") 
    println(x.x) 
} 

Dieser druckt 0 ich davon aus, dass, wenn der Compiler die var x:Int = 0 erreicht, hat der Körper des Haupt Konstruktor beendet. Liege ich falsch? Wie sonst könnten Sie Instanzvariablen in Scala deklarieren (vorausgesetzt, ich möchte sie nicht in meinem Konstruktor haben)?

+0

Ok, lass uns abwarten. – Geo

+1

Jede Codezeile, die sich nicht in einem def (Methodenkörper) befindet, ist ein Konstruktorcode. Der Val- und Var-Initialisierungscode ist darin enthalten, und der Konstruktor ist die Top-Bottom-Akkumulation des gesamten Codes. Beachten Sie, dass dies Dinge wie Methoden * Aufrufe * zwischen val, var und def * Definitionen * eingefügt enthält. –

Antwort

7

Denken Sie daran, dies die erste Zeile des Konstrukteurs machen, dass Ihr Code übersetzt in etwas ähnliches (aber nicht genau) zu diesem:

public class A { 

    private final String g; 
    private int x; 

    public A(String g) { 
    this.g = g; 
    x_$eq(x() + g.length()); 
    x = 0; 
    } 

    public void x_$eq(int arg0) { 
    x = arg0; 
    } 

    public int x() { 
    return x; 
    } 

    public String g() { 
    return g; 
    } 
} 

Vars, die in (Nicht-Konstruktor-) Methoden definiert sind, werden in tatsächliche lokale Variablen übersetzt.

Nicht sicher, ob dies die Argumentation so sehr erklärt, dass sie einen der Unterschiede hervorhebt.


EDIT - Changed "Übersetzung" von scala für Klarheit und die Fähigkeit, Java genauer darzustellen, was geschieht.

+0

Also, warum war '_x' 3 nicht? So lese ich die Code-Darstellung. – Geo

+0

Aber wie wird 'x' behandelt? Als lokale Variable? Erklärt der Compiler das? – Geo

+0

Bearbeitet, um die Zuweisung für das private Feld auf 0 zu zeigen. –

4

ändern diese:

class A(val g:String) { 
    x += g.length 
    var x:Int = 0 
} 

zu

class A(val g:String) { 
    var x = g.length 

} 
+0

Warum nicht einfach ein "val" machen? Es gibt keine Hinweise aus dem Beispielcode, der geändert werden muss. –

+0

Ja, das wäre besser –

4

var x: Int = 0

class A(val g:String) { 
    var x:Int = 0 
    x += g.length 
} 
7

Ihre Verwirrung resultiert aus einem Missverständnis, wie Konstrukteure in Scala arbeiten. Insbesondere wollen wir die Scala Code übersetzen Sie in Java geschrieben:

class A(val g:String) { 
    x += g.length 
    var x:Int = 0 
} 

wird

public class A { 
    public A(String g) { 
     x += g.length(); 
     x = 0; 
    } 
    private int x; 
} 

Der Grund ist einfach. Der gesamte Körper einer Klasse in Scala ist der primäre Konstruktor für diese Klasse. Das bedeutet, dass die Anweisungen darin und die Initialisierungen val und var Anweisungen sind, werden in der Reihenfolge ausgeführt, in der sie gefunden werden.

PS: Hier ist die tatsächliche, wahre Wiedergabe dieses Codes.

Scala 2,7

C:\Users\Daniel\Documents\Scala\Programas> scalac -print A.scala 
[[syntax trees at end of cleanup]]// Scala source: A.scala 
package <empty> { 
    class A extends java.lang.Object with ScalaObject { 
    @remote def $tag(): Int = scala.ScalaObject$class.$tag(A.this); 
    <paramaccessor> private[this] val g: java.lang.String = _; 
    <stable> <accessor> <paramaccessor> def g(): java.lang.String = A.this.g; 
    private[this] var x: Int = _; 
    <accessor> def x(): Int = A.this.x; 
    <accessor> def x_=(x$1: Int): Unit = A.this.x = x$1; 
    def this(g: java.lang.String): A = { 
     A.this.g = g; 
     A.super.this(); 
     A.this.x_=(A.this.x().+(g.length())); 
     A.this.x = 0; 
    () 
    } 
    } 
} 

Scala 2,8

C:\Users\Daniel\Documents\Scala\Programas>scalac -print A.scala 
[[syntax trees at end of cleanup]]// Scala source: A.scala 
package <empty> { 
    class A extends java.lang.Object with ScalaObject { 
    <paramaccessor> private[this] val g: java.lang.String = _; 
    <stable> <accessor> <paramaccessor> def g(): java.lang.String = A.this.g; 
    private[this] var x: Int = _; 
    <accessor> def x(): Int = A.this.x; 
    <accessor> def x_=(x$1: Int): Unit = A.this.x = x$1; 
    def this(g: java.lang.String): A = { 
     A.this.g = g; 
     A.super.this(); 
     A.this.x_=(A.this.x().+(g.length())); 
     A.this.x = 0; 
    () 
    } 
    } 
} 
+0

Gut zu sehen, dass Sie so viel Schwierigkeiten haben wie ich, Java frei zu geben, ohne in Scala-Ismen zu rutschen. Sie haben ein Semikolon verpasst und den Initializer nicht existent-in-java verwendet. –

+0

Ich wünschte Java würde den Geist schon aufgeben. :-) –

+0

Ok, der Code wurde korrigiert und kompiliert, um sicherzugehen. Warum kann Java nicht vernünftig sein? :-) –

0

Warum Sie x Referenz macht Scala lassen, bevor Sie es erklärt? In jedem anderen Bereich wäre dies illegal.

scala> def foo(g:String) = { x+=1; var x=0; x} 
<console>:4: error: forward reference extends over definition of variable x 
     def foo(g:String) = { x+=1; var x=0; x}