scala 如果我的对象位于单独的源文件中,为什么它不是包 <root> 的成员?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9822008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is my object not a member of package <root> if it's in a separate source file?
提问by Martin McNulty
I'm having a problem accessing an object defined in the root package. If I have all my code in one file, it works fine, but when I split it across two files, I can't get it past the compiler.
我在访问根包中定义的对象时遇到问题。如果我将所有代码都放在一个文件中,它可以正常工作,但是当我将它拆分为两个文件时,我无法通过编译器。
This works fine:
这工作正常:
All in one file called packages.scala:
全在一个文件中,称为packages.scala:
object Foo
val name = "Brian"
}
package somepackage {
object Test extends App {
println(Foo.name)
}
}
Witness:
证人:
$ scalac packages.scala
$ scala -cp . somepackage.Test
Brian
But if I split the code across two files:
但是,如果我将代码拆分为两个文件:
packages.scala
packages.scala
object Foo {
val name = "Brian"
}
packages2.scala
packages2.scala
package somepackage {
object Test extends App {
println(Foo.name)
}
}
it all fails:
这一切都失败了:
$ scalac packages.scala packages2.scala
packages2.scala:3: error: not found: value Foo
So I try to make the reference to Fooabsolute:
所以我尝试引用Foo绝对:
...
println(_root_.Foo.name)
...
But that doesn't work either:
但这也不起作用:
$ scalac packages.scala packages2.scala
packages2.scala:3: error: object Foo is not a member of package <root>
If Foois not a member of the root package, where on earth isit?
如果Foo不是根包的成员,在地球上是它?
回答by Debilski
I think this is the relevant part in the spec:
我认为这是规范中的相关部分:
Top-level definitions outside a packaging are assumed to be injected into a special empty package. That package cannot be named and therefore cannot be imported. However, members of the empty package are visible to each other without qualification.
假设包装外的顶级定义被注入到一个特殊的空包中。该包无法命名,因此无法导入。但是,空包的成员是相互可见的,没有资格。
Source Scala Reference §9.2 Packages.
But don't ask me why it works if you have the following in packages2.scala:
但是,如果您有以下内容,请不要问我为什么它会起作用packages2.scala:
object Dummy
package somepackage {
object Test extends App {
println(Foo.name)
}
}
回答by Matthew Farwell
Foo is a member of the root package, but you can't refer to it. It's a generic thing with JVM languages, (see How to access java-classes in the default-package?for Groovy, What's the syntax to import a class in a default package in Java?). It's the same for Scala.
Foo 是根包的成员,但你不能引用它。这是 JVM 语言的通用内容,(请参阅如何访问默认包中的 java 类?对于 Groovy,在 Java 中的默认包中导入类的语法是什么?)。Scala 也是如此。
From the Java answer:
从Java答案:
You can't import classes from the default package. You should avoid using the default package except for very small example programs.
From the Java language specification:
It is a compile time error to import a type from the unnamed package.
您不能从默认包中导入类。除了非常小的示例程序外,您应该避免使用默认包。
来自 Java 语言规范:
从未命名的包中导入类型是编译时错误。
The reason it works in one single file is because everything is available to the compiler at once, and the compiler copes with it. I suspect that this is to allow scripting.
它在单个文件中工作的原因是因为编译器可以立即使用所有内容,并且编译器会处理它。我怀疑这是为了允许编写脚本。
Moral of the story: don't use the default package if you're not scripting.
故事寓意:如果您不编写脚本,请不要使用默认包。
回答by Logister
Ran into this when trying to import the main Appentrypoint into a test. This may be an evil hack, but putting package scalaat the top of the entrypoint definition seems to have made the object globally available. This may be evil, but it works.
尝试将主App入口点导入测试时遇到了这个问题。这可能是一个邪恶的黑客攻击,但放在package scala入口点定义的顶部似乎使该对象全局可用。这可能是邪恶的,但它有效。
E.g. /src/main/scala/EntryPoint.scala
例如 /src/main/scala/EntryPoint.scala
package scala
object EntryPoint extends App {
val s = "Foo"
}
/src/test/scala/integration/EntryPointSuite.scala
/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")
}
}

