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中声明实例变量(假设我不想在构造函数中使用它们)?
请记住,您的代码会转换为与此类似的内容(但不完全相同):
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,以及更准确地表示正在发生的事情的能力.
您对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中类的整个主体是该类的主要构造函数.这意味着它中的语句,以及初始化val和var语句将按它们被找到的顺序执行.
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)