2016-07-25 5 views
0

私はScalaを学んでいて、いくつかのコマンドライン実行ファイルを書こうとしています。Scala:構文の実行時にエラーが発生しましたか?

私は2つのバージョンのHelloWorldを持っていますが、それは意味的には同じだと思っていました。 HelloWorld.scalaがコンパイルされ、コマンドラインから正常に実行されます。 HelloWorld2.scalaはコンパイルされますが、実行時エラーが発生します。

私の質問:2つは意味的に同じだと思いますが、2番目のものがランタイムエラーを引き起こすのはなぜですか?ここで

は作業例です:

// HelloWorld.scala 

object HelloWorld { 

    def main(args: Array[String]): Unit = { 
    println("Hello, World!") 
    } 
} 

はここで壊れた例です:

// HelloWorld2.scala 

object HelloWorld2 { 

    def main 
    : Array[String] => Unit 
    = args   => { 
     println("Hello, World!") 
    } 
} 

ここでコンソール出力です:

java.lang.NoSuchMethodException: HelloWorld2.main([Ljava.lang.String;) 
    at java.lang.Class.getMethod(Class.java:1778) 
    at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:66) 
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101) 
    at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22) 
    at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39) 
    at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29) 
    at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39) 
    at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:65) 
    at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87) 
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98) 
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103) 
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) 
+1

'HelloWorld2.main'を探していますが、あなたは' HelloWorld.main'しか持っていません。ファイルと一致するようにクラス名を変更するか、ファイル名をクラスに合わせて変更してください(つまり、壊れたサンプルのコードをHelloWordにコピーしてください)。スカラー) –

+1

ここでは二つの異なるものがあります: 'Array' [String]'を持ち、戻り値の型が 'Unit'の' main'メソッドと、 'main'メソッドとの間に引数をとらず、配列[String] 'と戻り値の型は' Unit'です。 – Jesper

+0

@TheDark、オブジェクト名を指摘していただきありがとうございます。 TBH、それは私の質問のちょうどタイプミスでした:私が実際に作業していたファイルはオブジェクトに正しく名前を付けました。 –

答えて

5

かかわらず、Scalaは関数にメソッドを変換できること(η拡張、時には自動)、彼らはここにdifferent thingsです。主な違いは、スカラーがJVM用に異なるバイトコードを生成することです。

あなたの例の話、あなたは実際にクラスFunction1のオブジェクトを返すメソッドdef定義:

def main: Function1[Array[String], Unit] //you could even put `val` here 

JVMは完全に異なるシグネチャを持つメソッドが必要です。

def main(args: Array[String]): Unit 

JVMのため、関数はクラスFunctionNのインスタンスにすぎません。スカラーコンパイラはそれを自動的にメソッドに変換しません。 applyFunction1クラスのちょうど方法、()applyを呼び出すためだけの構文糖であることを

def main(args: Array[String]): Unit = main.apply(args) 

def main: Array[String] => Unit = ...// or `val main` 

注:手動変換は次のようになります。

更新日:

ちょうど追加情報です。 @のSOM-snyttが指摘したように、scalaのランナーはmainの署名について、より柔軟であるので、これは:

def main(args: Array[String]): Int 

scala HelloWorldのために動作しますが、java HelloWorldのために動作しません - それはUnitが必要になります(void)戻り値の型として返します。私は、javacscalacのJavaコードをコンパイルする間のいくつかの違いを思い出すこともできます。つまり、scala/scalacが進化しているので、scalaはもっと機能が豊富なmainメソッドを実行する可能性があります。スクリプトをコンパイルして実行することもできます。

+1

ちょうど 'java'はそのsigを必要とします。 'def main(args:Array [String]):Int'を定義すると、船尾警告が表示されますが、' scala'がそれを実行します。 Scalaははるかに柔軟性があります。デフォルトで結果の値を出力するといいでしょう。また、docリンクのためのthx。 –

+0

ありがとうございました。私はScalaを全く慣用的に書こうとしていました。すべての型シグネチャを別の行に書き出しました。残念ながら、私はそれをやめなければならないようです。 –

関連する問題