为什么Scala程序应该有一个main方法或扩展App特性?

为什么Scala程序应该有一个main方法或扩展App特性?,scala,Scala,我试图通过阅读《不耐烦的人的Scala》一书来学习Scala。这本书一开始说要在REPL中输入代码,但这变得有点乏味,所以我开始将代码放在一个文件中,然后通过键入scala myApp.scala从命令行运行它。一切似乎都很顺利。我决定让我的程序运行起来更容易一点,把这行代码放在#/usr/bin/env scala位于顶部,因此我可以从命令行键入/myFile.scala。一切都很顺利 后来,这本书说“每个Scala程序必须从对象的mainmethod…”开始,并给出了一个例子。紧接着,它说“

我试图通过阅读《不耐烦的人的Scala》一书来学习Scala。这本书一开始说要在REPL中输入代码,但这变得有点乏味,所以我开始将代码放在一个文件中,然后通过键入
scala myApp.scala
从命令行运行它。一切似乎都很顺利。我决定让我的程序运行起来更容易一点,把这行代码放在
#/usr/bin/env scala
位于顶部,因此我可以从命令行键入
/myFile.scala
。一切都很顺利

后来,这本书说“每个Scala程序必须从对象的
main
method…”开始,并给出了一个例子。紧接着,它说“您可以扩展
App
特性并将程序代码放入构造函数体中,而不是为应用程序提供
main
方法”,并给出一个示例

我为什么要做这些事情?

我试着把我的代码放在一个对象的
main
方法中,它仍然有效,但是这个对象和
main
方法对我来说似乎是无用的垃圾

我尝试将代码放在扩展
App
的对象中,但当我尝试直接从命令行运行它时,它没有做任何事情。当我运行scalac
scalac
然后运行scala MyApp时,它运行得很好,但对于我正在进行的小玩具项目来说,这些步骤似乎是无用的

使用
main
方法创建对象或扩展
App
的对象的目的是什么


编辑:有人将此问题标记为“scala脚本和应用程序之间的差异”的重复。我想说,它可以说不是重复的,因为它是关于拥有
main
方法并从
App
扩展而来的,而不是关于“脚本”和“应用程序”这两个词的含义。不过,这很接近,所以我的问题可能没有必要。我不知道该如何对待这个问题。您可以随意关闭或打开它。

如果您所做的只是您正在进行的“小玩具项目”,则可能没有任何意义。对于较大的项目,一个
main()
方法创建了与Java的兼容性,并且还向代码的读者指示“它从哪里开始”。当一个项目很大(成百上千个文件)并且您第一次接触它时,您可能想知道“我如何运行它?”,“执行从哪里开始?”。java从C++中继承了这个约定,它从C语言中得到的都是函数,需要告诉编译器哪个函数需要编译成“执行的开始”。
当您手工执行代码时,您会说“scala myApp.scala”,这会向scala解释器解释要执行哪个类。但是,如果您编写一个更大的应用程序,编译两个类并将它们放在一个JAR中,您需要一种方法来告诉JVM首先执行什么:您指定一个对象的名称,按照约定,在该对象中执行将从
main(args:Array[String])

开始如果您所做的都是“小玩具项目”,那么可能没有任何意义你正在工作。对于较大的项目,一个
main()
方法创建了与Java的兼容性,并且还向代码的读者指示“它从哪里开始”。当一个项目很大(成百上千个文件)并且您第一次接触它时,您可能想知道“我如何运行它?”,“执行从哪里开始?”。java从C++中继承了这个约定,它从C语言中得到的都是函数,需要告诉编译器哪个函数需要编译成“执行的开始”。
当您手工执行代码时,您会说“scala myApp.scala”,这会向scala解释器解释要执行哪个类。但是,如果您编写一个更大的应用程序,编译两个类并将它们放在一个JAR中,那么您需要一种方法来告诉JVM首先执行什么:指定一个对象的名称,在该对象中(按照约定)执行将从
main(args:Array[String])

开始。您可以使用这两种方法运行程序。但是脚本用于小程序,而声明
main
方法用于大程序。传统上,运行字节码的JVM识别
main
方法,并从main方法的第一行开始执行程序。

您可以使用这两种方法运行程序。但是脚本用于小程序,而声明
main
方法用于大程序。传统上,运行字节码的JVM识别
main
方法,并从main方法的第一行开始执行程序。

小程序在没有main方法的情况下显示结果的原因是,您实际上没有使用scala编译器。该程序只是使用scala解释器。 所以像这样的程序:

A.scala:

println("just the interpreter")
object B {
    println("won't show up")
}
object C {
    def main(args: Array[String]) =
        println("shows up")
}
object D extends App {
    println("shows up")
}
将运行并给出结果。但是,尝试使用scalac编译此程序将产生错误:
A.scala:1:错误:预期的类或对象定义

通常scala项目不是一个文件中的指令列表。一旦您开始用类和对象构建应用程序,您就会发现您的程序不会产生任何结果

B.scala:

println("just the interpreter")
object B {
    println("won't show up")
}
object C {
    def main(args: Array[String]) =
        println("shows up")
}
object D extends App {
    println("shows up")
}
要获得结果,您需要添加一个main方法来告诉scala应用程序的入口点在哪里

C.scala:

println("just the interpreter")
object B {
    println("won't show up")
}
object C {
    def main(args: Array[String]) =
        println("shows up")
}
object D extends App {
    println("shows up")
}
为了方便起见,apptrait允许您通过简单地扩展App将任何对象转换为可执行程序。扩展此特性将使整个对象体成为主要方法

D.scala:

println("just the interpreter")
object B {
    println("won't show up")
}
object C {
    def main(args: Array[String]) =
        println("shows up")
}
object D extends App {
    println("shows up")
}
现在,您不能简单地调用
scala D.scala
来获得结果。首先需要调用
scalacd.sc