Reputation: 6781
EDIT: Main method is not called in Scala script is related (in particular, the answer from Régis Jean-Gilles). This post gives more details to describe the issue. And the answer (by suish) give a more practical demonstration to explain the behaviour of the scala command.
Content of MiniScalaApp.scala
object MiniScalaApp {
def main(args: Array[String]) = {
println(s"Scala Version: ${scala.util.Properties.scalaPropOrElse("version.number", "unknown")}")
println(new Dinosaur("Tyrannotitan", 4900))
println(new Dinosaur("Animantarx ", 300))
}
class Dinosaur (name:String, weightKG: Int) {
override def toString = f"$name, Weight: $weightKG kg"
}
}
Executed at the command line by:
$ scala /myProject/src/main/scala/MiniScalaApp.scala
Produces the expected output:
Scala Version: 2.11.7
Tyrannotitan, Weight: 4900 kg
Animantarx, Weight: 300 kg
However, if the Dinosaur class is placed outside of the singleton object MiniScalaApp then the scala command produces no console output, no error message.
object MiniScalaApp {
def main(args: Array[String]) = {
println(s"Scala Version: ${scala.util.Properties.scalaPropOrElse("version.number", "unknown")}")
println(new Dinosaur("Tyrannotitan", 4900))
println(new Dinosaur("Animantarx ", 300))
}
}
class Dinosaur (name:String, weightKG: Int) {
override def toString = f"$name, Weight: $weightKG kg"
}
In this 2nd version, to get the console output, the code must be compiled first and then run the MiniScalaApp.class separately
$ scalac /myProject/src/main/scala/MiniScalaApp.scala
$ scala MiniScalaApp
Question: What is the reason the scala command treats the code differently?
Upvotes: 4
Views: 161
Reputation: 3343
scala -help
explains all.
A file argument will be run as a scala script unless it contains only self-contained compilation units (classes and objects) and exactly one runnable main method. In that case the file will be compiled and the main method invoked. This provides a bridge between scripts and standard scala source.
so the latter case which is defining object and class, It will run the code as script. in another way to say, what It does is exactly the same as...
scala> :paste
// Entering paste mode (ctrl-D to finish)
object MiniScalaApp {
def main(args: Array[String]) = {
println(s"Scala Version: ${scala.util.Properties.scalaPropOrElse("version.number", "unknown")}")
println(new Dinosaur("Tyrannotitan", 4900))
println(new Dinosaur("Animantarx ", 300))
}
}
class Dinosaur (name:String, weightKG: Int) {
override def toString = f"$name, Weight: $weightKG kg"
}
// Exiting paste mode, now interpreting.
defined object MiniScalaApp
defined class Dinosaur
only defining.so you need to call it explicitly.
MiniScalaApp.main(Array())
In addition to that, object Foo extends App
can't be used if the file have only one top-lebel object.def main
is required.
Upvotes: 1
Reputation: 6242
Seems like you need to invoke the main
method explicitly if there is more than 1 top-level class/object:
object MiniScalaApp {
def main(args: Array[String]) = {
println(s"Scala Version: ${scala.util.Properties.scalaPropOrElse("version.number", "unknown")}")
println(new Dinosaur("Tyrannotitan", 4900))
println(new Dinosaur("Animantarx ", 300))
}
}
class Dinosaur (name:String, weightKG: Int) {
override def toString = f"$name, Weight: $weightKG kg"
}
MiniScalaApp.main(args);
See here: Main method is not called in Scala script
Upvotes: 0