需要一些Scala实例变量的帮助

Geo*_*Geo 5 java oop language-features scala

假设这个Java代码:

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

   private int x = 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我创建A的实例,像这样:

A a = new A("geo");
Run Code Online (Sandbox Code Playgroud)

在这个调用之后,x的值将是3.我在Scala代码中做错了什么?

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

object x extends Application {
  val x = new A("geo")
  println(x.x)
}
Run Code Online (Sandbox Code Playgroud)

这打印0.我假设当编译器到达时var x:Int = 0,主构造函数的主体已经结束.我错了吗?你怎么能在Scala中声明实例变量(假设我不想在构造函数中使用它们)?

Mit*_*ins 7

请记住,您的代码会转换为与此类似的内容(但不完全相同):

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

但是(非构造函数)方法中定义的变量会被转换为实际的局部变量.

不确定这是否能解释其中的原因之一就是突出其中一个差异.


编辑 - 为了清晰起见,将scala中的"翻译"更改为java,以及更准确地表示正在发生的事情的能力.


Dan*_*ral 7

您对Scala中的构造函数如何工作的误解导致了您的困惑.具体来说,让我们将您发布的Scala代码翻译成Java:

class A(val g:String) {
  x += g.length
  var x:Int = 0
}
Run Code Online (Sandbox Code Playgroud)

public class A {
   public A(String g) {
      x += g.length();
      x = 0;
   }
   private int x;
}
Run Code Online (Sandbox Code Playgroud)

原因很简单.Scala中类的整个主体是该类的主要构造函数.这意味着它中的语句,以及初始化valvar语句将按它们被找到的顺序执行.

PS:这是该代码的实际真实再现.

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;
      ()
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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;
      ()
    }
  }
}
Run Code Online (Sandbox Code Playgroud)