Нуждаюсь в некоторой помощи с переменными экземпляра Scala

Примите этот код Java:

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

   private int x = 0;
}

Если я создаю экземпляр A, как это:

A a = new A("geo");

после этого вызова значение 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)
}

Это печатает 0. Я предположил это, когда компилятор достигает var x:Int = 0, тело основного конструктора закончилось.Я неправ? Как еще Вы могли объявить переменные экземпляра в Scala (предполагающий, что я не хочу их в своем конструкторе)?

5
задан Geo 16 December 2009 в 21:30
поделиться

5 ответов

Имейте в виду, что ваш код переводится во что-то похожее (но не совсем) на это:

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;
  }
}

Но переменные, определенные в методах (не являющихся конструктором), переводятся в фактические локальные переменные.

Не уверен, что это объясняет рассуждения настолько, насколько подчеркивает одно из различий.


РЕДАКТИРОВАТЬ - Изменен «перевод» со scala на java для ясности и возможности более точно представлять, что происходит.

7
ответ дан 18 December 2019 в 07:09
поделиться

Your confusion results from a misunderstanding of how constructors in Scala works. Specifically, let's translate the Scala code you posted into Java:

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

becomes

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

The reason is simple. The whole body of a class in Scala is the primary constructor for that class. That means the statements in it, and initializing val and var are statements, will be executed in the order they are found.

PS: Here is the actual, true rendition of that code.

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;
      ()
    }
  }
}
7
ответ дан 18 December 2019 в 07:09
поделиться

Измените это:

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

на

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

}
4
ответ дан 18 December 2019 в 07:09
поделиться

var x: Int = 0 сделайте это первой строкой конструктора

class A(val g:String) {  
   var x:Int = 0  
   x += g.length  
}
4
ответ дан 18 December 2019 в 07:09
поделиться

Почему Scala позволяет вам ссылаться на x до того, как вы его объявили? В любой другой области это было бы незаконно.

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}
0
ответ дан 18 December 2019 в 07:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: