问题描述
我刚刚开始学习Scala,我正在关注的许多教程都将不同表示形式的组合用于main
方法.除了熟悉的主要方法外,还使用了特征App
或Application
.看来Application
已被弃用,不建议使用,但是我找不到任何有关这些定义入口点的方法的详细说明.
I've just started learning Scala and many of the tutorials that I'm following are using a combination of different representations for a main
method. Aside from the familiar main method; there's also the use of traits App
or Application
.It appears that Application
has been deprecated and is not recommended, but I can't find any information that explains much beyond this about each of these ways to define an entry point.
所以,我想知道是否有人可以向我解释:
So, I'm wondering if someone could explain to me:
- 特征
App
和Application
如何工作? - 为什么不再推荐使用特征
Application
?App
特征有什么不同? - 在哪里应使用传统的main方法,何时应使用
App
来启动程序?两种方法有什么区别?
- How do the traits
App
andApplication
work? - Why is the trait
Application
no longer recommended and what does theApp
trait do that is different? - Where should I use the traditional main method and when should I use
App
to start my program? What's the difference between the two approaches?
推荐答案
特性实际上在其文档中进行了描述:
The problem with the Application
trait is actually described in its documentation:
这是一个棘手的问题.如果扩展Application
特性,则基本上是在创建Java类:
This is a tricky one. If you extend the Application
trait, you are basically creating a Java class:
class MyApplication implements Application {
static {
// All code goes in here
}
}
JVM在MyApplication
类上隐式同步运行上述类初始化程序.这样,可以确保在初始化MyApplication
的类之前不会创建任何实例.如果您从应用程序中产生一个再次需要访问MyApplication
实例的线程,则您的应用程序将死锁,因为类初始化仅在整个程序执行后才完成.这意味着一个悖论,因为只要程序正在运行,就无法创建任何实例.
The JVM runs the above class initializer implicitly synchronized on the MyApplication
class. This way, it is assured that no instance of MyApplication
is created before its class is initialized. If you spawn a thread from your application that again needs to access an instance of MyApplication
, your application would dead lock as the class initialization is only complete after the entire program has executed. This implies a paradox as no instance can be created as long as your program is running.
类初始化器不接受任何参数.同样,它会先运行,然后再将任何值传递给该类,因为在您甚至可以分配一个静态字段值之前,都需要执行该类初始化程序.因此,通常会在main
方法上收到的args
丢失.
A class initializer does not take any arguments. Also, it is run first, before any values could be handed to the class as the class initializer needs to be executed before you could even assign a static field value. Thus, the args
that you normally receive on a main
method are lost.
JVM会优化经常运行的代码.这样,可以确保没有浪费时间,而这并不是真正造成性能瓶颈的方法.但是,可以安全地假定static
方法仅执行一次,因为它们无法手动调用.因此,如果使用Application
特性,它将不会优化从类初始化程序运行的代码,而该类初始化程序是应用程序的main
方法代码.
The JVM optimizes code that is run frequently. This way, it makes sure that no run time is wasted on methods that are not really a performance bottle neck. However, it safely assumes that static
methods are only executed once as they cannot be invoked manually. Thus, it will not optimize the code that is run from a class initializer which is however your application's main
method code if you are using the Application
trait.
App
特性通过扩展 DelayedInit
. Scala编译器明确知道此特征,因此初始化代码不是从类初始化程序运行,而是从其他方法运行.请注意该特征唯一方法的名称引用:
trait Helper extends DelayedInit {
def delayedInit(body: => Unit) = {
println("dummy text, printed before initialization of C")
body
}
}
实现DelayedInit
时,Scala编译器将其实现类或对象的所有初始化代码包装到 for name 函数中,然后传递给delayedInit
方法.没有初始化代码直接执行.这样,您还可以在运行初始化程序之前运行代码,例如,这允许Scala将应用程序的运行时度量标准打印到控制台,该控制台包裹在程序的入口和出口周围.但是,有一些警告因此,不推荐使用这种方法并使用DelayedInit
.您实际上应该仅依靠App
特质来解决Application
特质带来的问题.您不应该直接实现DelayedInit
.
When implementing DelayedInit
, the Scala compiler wraps any initialization code of its implementing class or object into a for name function which is then passed to the delayedInit
method. No initialization code is executed directly. This way, you can also run code before an initializer is run what allows Scala for example to print an application's runtime metrics to the console which is wrapped around the program's entry point and exit. However, there are some caveats of this approach and using DelayedInit
is therefore deprecated. You should really only rely on the App
trait which solves the problems that are imposed by the Application
trait. You should not implement DelayedInit
directly.
如果愿意,您仍然可以定义main
方法,只要在object
中定义它即可.这主要是样式问题:
You can still define a main
method if you want to, as long as you define it in an object
. This is mostly a matter of style:
object HelloWorld {
def main(args: Array[String]) {
println("Hello, world!")
}
}
这篇关于在斯卡拉;我应该使用App特性吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!