main,App,Applicationとか、冒頭からわかりにくいぞScalaさん。
なぜmainの記述方法が3つも用意されているのだ。「def main(args: Array[String])」の1行を省略させたいがためか、それをJavaとの比較で優位性を強調したいのか。Scalaの学習者は、冒頭から余計に悩まされることになる。
object Hi {
def main(args: Array[String]) = {
println("Hi! main")
}
}
object Hi extends Application {
println("Hi! Hi! Application")
}
上記の3つは、どれも似たような動作をする。Applicationの方は推奨ではないらしく、Appに書き換わる経過措置のようだ。
object Hi extends App {
println("Hi! Hi! App")
}
ScalaはLispのようにコードとデータを区別する必要もない。Scalaでは言いすぎだが、Lispは正しくそうだ。Scalaの開発者はそれを意識しているのか、サンプルコードにソースコードを読み込んで処理させるものが目立つ。コードをread-evalして実行させたいのだ。Lispでは常套のことだった。上記のAppの実装もそれに近い。App内の実行ステートメントを保持して、mainの中でevalしている感じだ。
と書くとコンパイルエラーにはならず、以下のように表示される。mainは最後に呼び出されていることが分かる。
object Hi {
println("Hi! before")
def main(args: Array[String]) = {
println("Hi! main")
}
println("Hi! after")
}
では次にAppで試す。mainはoverrideしている。
Hi! before
Hi! after
Hi! main
これだと以下のようにmainしか表示されない。
object Hi extends App {
println("Hi! before")
override def main(args: Array[String]) = {
println("Hi! main")
}
println("Hi! after")
}
before、afterの実行ステートメントは実行されない。それを実行してくれるmainを書き換えているからだ。最後にApplicationで試す。mainは同様にoverrideしてみる。
Hi! main
これだと以下のようにbefore,after,mainの順に表示される。最初の通常のmainの記述と同じ結果だ。
object Hi extends Application {
println("Hi! before")
override def main(args: Array[String]) = {
println("Hi! main")
}
println("Hi! after")
}
この結果から、Appのみは、記述された実行ステートメントを保持して、mainの内部でevalしているようだ。必要ですか、Appが。そもそも、def mainの外に書いたprintln("Hi! before")やprintln("Hi! after")が実行されるというのは問題のない仕様なのだろうか。
Hi! before
Hi! after
Hi! main