ルートパッケージで定義されたオブジェクトへのアクセスに問題があります。すべてのコードが1つのファイルに含まれている場合は正常に機能しますが、2つのファイルに分割すると、コンパイラーを通過できません。
これは正常に機能します。
packages.scala
と呼ばれるオールインワンファイル:
object Foo
val name = "Brian"
}
package somepackage {
object Test extends App {
println(Foo.name)
}
}
証人:
$ scalac packages.scala
$ scala -cp . somepackage.Test
Brian
しかし、コードを2つのファイルに分割すると、次のようになります。
packages.scala
object Foo {
val name = "Brian"
}
packages2.scala
package somepackage {
object Test extends App {
println(Foo.name)
}
}
それはすべて失敗します:
$ scalac packages.scala packages2.scala
packages2.scala:3: error: not found: value Foo
だから私はFoo
絶対への参照を作ろうとします:
...
println(_root_.Foo.name)
...
しかし、それも機能しません。
$ scalac packages.scala packages2.scala
packages2.scala:3: error: object Foo is not a member of package <root>
Foo
がルートパッケージのメンバーでない場合、いったいどこでis it?
これが仕様の関連部分だと思います。
パッケージ外のトップレベルの定義は、特別な空のパッケージに挿入されると想定されています。そのパッケージには名前を付けることができないため、インポートできません。ただし、空のパッケージのメンバーは、資格なしで相互に表示されます。
ソース Scalaリファレンス§9.2パッケージ 。
ただし、packages2.scala
に次の情報がある場合、なぜ機能するのか私に聞かないでください。
object Dummy
package somepackage {
object Test extends App {
println(Foo.name)
}
}
Fooはルートパッケージのメンバーですが、参照することはできません。これはJVM言語では一般的なことです(Groovyの場合は デフォルトパッケージのJavaクラスにアクセスする方法 を参照してください Javaのデフォルトパッケージにクラスをインポートするための構文は何ですか?) )。 Scalaについても同じです。
Java回答から:
デフォルトのパッケージからクラスをインポートすることはできません。非常に小さなサンプルプログラムを除いて、デフォルトのパッケージの使用は避けてください。
Java言語仕様から:
名前のないパッケージから型をインポートすると、コンパイル時にエラーが発生します。
1つのファイルで機能する理由は、コンパイラーがすべてを一度に使用でき、コンパイラーがそれに対処するためです。これはスクリプトを許可するためだと思います。
話の教訓:スクリプトを作成していない場合は、デフォルトのパッケージを使用しないでください。
メインのApp
エントリポイントをテストにインポートしようとしたときに、これに遭遇しました。これは邪悪なハックかもしれませんが、package scala
エントリポイント定義の上部で、オブジェクトがグローバルに使用可能になっているようです。これは悪かもしれませんが、機能します。
例えば。 /src/main/scala/EntryPoint.scala
package scala
object EntryPoint extends App {
val s = "Foo"
}
/src/test/scala/integration/EntryPointSuite.scala
package integration
import org.scalatest.FlatSpec
class EntryPointSuite extends FlatSpec {
"EntryPoint" should "have property s" in {
val ep = EntryPoint.main()
assert(ep.s == "Foo")
}
}