Нужна помощь для объяснения проблемы скалы - PullRequest
4 голосов
/ 04 июня 2011

У меня есть два класса scala (и их Java-код, когда я использую javap -private для чтения файла класса).

Когда я использую n и d в методе toString, он сгенерирует приватное поле члена в классе. Это почему? Я немного растерялся.

Scala # 1:

class Rational(n: Int, d: Int) {

}

эквивалент из javap:

public class com.zjffdu.tutorial.scala.Rational
extends java.lang.Object
implements scala.ScalaObject{
    public com.zjffdu.tutorial.scala.Rational(int, int);
}

Scala # 2:

class Rational(n: Int, d: Int) {
  override def toString() = n + "/" + d
}

эквивалент из javap:

public class com.zjffdu.tutorial.scala.Rational
extends java.lang.Object
implements scala.ScalaObject{
    private final int n;
    private final int d;
    public java.lang.String toString();
    public com.zjffdu.tutorial.scala.Rational(int, int);
}

Ответы [ 3 ]

7 голосов
/ 04 июня 2011

Ну, значения n и d должны быть как-то доступны изнутри тела toString, верно? В противном случае вы не могли бы их использовать. Все может произойти между тем, когда вы создаете новый экземпляр, а n и d оказываются в стеке, и когда вы вызываете toString, а n и p давно исчезают из стека. Таким образом, компилятор автоматически сохраняет значение в полях - даже если вы не объявляете их как (private) val s в своем коде. Компилятор сделает это для всех переменных конструктора, которые используются за пределами конструктора ваших классов (помните, что конструктор класса - это фактически все тело самого класса, за исключением определений val и def).

3 голосов
/ 04 июня 2011

Scala примет аргументы конструктора, даже если они не объявлены val или var, и добавит их как частные поля в класс, если их когда-либо потребуется использовать вне конструктора.

В вашем случае, toString можно вызывать задолго после создания объекта.Таким образом, эти параметры должны быть сохранены в созданном экземпляре.

2 голосов
/ 04 июня 2011

Ну, тут еще веселее.Если вы попробуете это:

class Rational(n: Int, d: Int) {
  override val toString = n + "/" + d
}

Тогда частные переменные снова исчезнут!

public class Rational extends java.lang.Object implements scala.ScalaObject{
    private final java.lang.String toString;
    public java.lang.String toString();
    public Rational(int, int);
}

Разница в том, что когда вы используете d и n в методе, они имеютбыть сохраненным.Если они не используются в методе, только в конструкторе (например, val initialization), тогда они не должны существовать как члены каждого экземпляра.Взгляните на декомпилированную версию def toString:

public java.lang.String toString();
  Code:
   0:   new     #10; //class scala/collection/mutable/StringBuilder
   3:   dup
   4:   invokespecial   #14; //Method scala/collection/mutable/StringBuilder."<init>":()V
   7:   aload_0
   8:   getfield        #19; //Field n:I
   11:  invokevirtual   #23; //Method scala/collection/mutable/StringBuilder.append:(I)Lscala/collection/mutable/StringB
uilder;
   14:  ldc     #25; //String /
   16:  invokevirtual   #28; //Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collectio
n/mutable/StringBuilder;
   19:  aload_0
   20:  getfield        #30; //Field d:I
   23:  invokestatic    #36; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
   26:  invokevirtual   #28; //Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collectio
n/mutable/StringBuilder;
   29:  invokevirtual   #38; //Method scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String;
   32:  areturn

См. Строки 8 и 20?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...