Scala中奇怪的行为在类/对象初始化中 [英] Scala strange behavior in class/object initialization

查看:134
本文介绍了Scala中奇怪的行为在类/对象初始化中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

Scala和向前引用

在Scala中:

object Strange extends App {
  val x = 42
  Console.println(x) // => outputs "42", as expected
}



版本2



Version 2

object Strange extends App {
  Console.println(x) // => "0" ?!
  val x = 42
}

这也是与相同的问题, class

class StrangeClass {
  Console.println(x) // => still "0"
  val x = 42
}

object TestApp extends App {
  new StrangeClass()
}

正常方法的正文中没有这样的问题:

There are no such issue with regular method's body:

def nonStrangeMethod {
  Console.println(y) // => fails with "not found: value y", as expected
  y = 42
}

如果我们在val声明中添加final,行为会发生巨大变化:

And behavior changes dramatically if we'd add "final" to val declaration:

class StrangeClass {
  Console.println(x) // => "42", but at least that's expected
  final val x = 42
}

对于记录,以下Java静态(Scala的对象)对应:

For records, the following Java static (Scala's object) counterpart:

public class Strange {
    static {
        System.out.println(x);
    }
    static int x = 42;

    public static void main(String[] args) {}
}


$ b b

无法使用plain&在第3行和Java非静态(Scala的 class )对应部分:无法引用之前定义的字段的可理解错误:

fails compilation with plain & understandable error "Cannot reference a field before it is defined" on line #3 and Java non-static (Scala's class) counterpart:

public class Strange {
    Strange() {
        System.out.println(x);
        int x = 42;
    }

    public static void main(String[] args) {
        new Strange();
    }
}

显然失败,x无法解析为变量on line#3。

obviously fails with "x cannot be resolved to a variable" on line #3.

推荐答案

这是因为 App 其使用延迟初始化。从 中对应用程式进行编程

It's because of the App trait which uses delayed initialization. From Programming in Scala regarding the App trait:


大括号之间的代码被收集到singleton对象的主要
构造函数中,并在类是
初始化时执行

The code between the curly braces is collected into a primary constructor of the singleton object, and is executed when the class is initialized

2.9.0版本也注意到了这一点:

The 2.9.0 release notes this too:


继承App特性的对象使用Scala 2.9' s
延迟初始化功能以执行整个身体作为
继承的main方法的一部分。

Objects inheriting the App trait instead make use of Scala 2.9’s delayed initialization feature to execute the whole body as part of an inherited main method.

code>不会执行Console.println(x),直到 Strange b
$ b

So Console.println(x) is not executed until Strange is ran where you get this as output:

scala> s.main(Array[String]())
0

code>之后 val x = 42 后输出:

If you add another Console.println(x) after val x = 42 then it prints out:

scala> s.main(Array[String]())
0
42

编译器知道在当前范围中存在 x ,但它会延迟其评估,直到它被执行,然后打印出 Int 这是 0

The compiler knows that x exists in the current scope but it delays evaluation of it until it is executed and then it prints out the default value for Int which is 0.

这篇关于Scala中奇怪的行为在类/对象初始化中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆