Scala println在使用App trait时无法正常工作

9
当我使用scala中的App trait时,无法运行println语句。
以下是一个简单的例子:
object HelloWorld {
  def main(args: Array[String]) {
    println("Hello, world!")
  }
}

但是一旦我引入这个特征,它就不起作用了。
object HelloWorld extends App {
  println("Hello, world!")
}

我没有收到任何错误信息,但是控制台上没有输出任何内容。
3个回答

10

你是否先编译它了(运行scalac HelloWorld.scala)?请查看此评论:http://www.scala-lang.org/node/9483#comment-40627

编辑以添加更多说明: 第一个版本实际上已经被编译了。没有显式main方法的Scala文件可以作为脚本运行而不编译。这意味着对于你的第二个版本,文件中的命令按顺序运行,就好像它们已经输入到解释器中一样——因此,HelloWorld对象被创建,但是没有在其上调用任何方法。有关Scala作为脚本语言的更多信息,请参见此处(滚动至步骤五):http://www.artima.com/scalazine/articles/steps.html


奇怪。这似乎是解释器的一个奇怪限制。为什么我需要编译类才能让它工作?特质在解释器中不起作用吗? - James McMahon
1
特质确实可以在解释器中使用,但 App 是一种特殊情况。通常会将其呈现为“App 在其实现对象内部包装代码的主要方法”,但实际上不是这样的-它将该代码放入称为 delayedInit 的东西中,当调用 main 方法而非创建对象时调用 delayedInit,这通常是在对象声明中调用裸代码的时候发生的。 - Kelsey Gilmore-Innis
1
没问题 - 如果你对Scala初始化的一些潜在陷阱感到好奇,Josh Suereth的新书《深入理解Scala》第4章中有更详细的描述 :) - Kelsey Gilmore-Innis
@James,@Kelsey,两种情况下都编译了 - 怎么可能不编译呢... JVM 运行的是字节码,而不是文本。如果您不声明外部对象并将其作为脚本运行,则您的命令会被包装在一个临时对象中进行编译/运行 - 但与运行 scalac 不同的是,.class 文件不会保存到磁盘上。某个时候有人决定,如果您的脚本由一个具有 main 方法的单个对象组成,而不是将其包装起来,它将只编译该对象并运行它。我认为,不对 App 做同样的事情似乎是一个疏忽,但这不是您应该依赖的行为。 - Luigi Plinge
@LuigiPlinge,说得好。该脚本的工作方式类似于在Scala“解释器”中运行代码 - 它被编译为临时对象,.class文件不会保存。 - Kelsey Gilmore-Innis

5

添加一行

object HelloWorld extends App {
  /* code */
}

HelloWorld.main(args)

在文件结尾处。
这个类定义了方法,但也需要被调用。

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接