这是因为在与 Java 库交互时,Scala 需要一种将 Java 的静态方法映射到 Scala 的单例对象的方法。
例如,如果您有以下 Java 类:
package pkg;
class Test {
public static void printHello() {
System.out.println("Hello");
}
}
我们如何printHello
在 Scala 中调用?它将如下所示:
import pkg.Test
Test.printHello()
如您所见,语法与调用 中的方法完全相同object Test
。从这个角度来看,Test
单例已经定义好了,你不能object
用相同的 FQN 定义两次。
这就是为什么你需要定义pkg.matchers.Test
,这样它就不会与pkg.Test
.
并且 Scala 的编译器足够聪明,可以判断出这pkg.matchers.Test
是一个无法使用new
关键字构造它的单例,所以当你编写时new Test(1)
,它是pkg.Test
而不是pkg.matchers.Test
. 这就是为什么您可以在代码示例中同时使用它们的原因。
实际上,您根本不需要type Test = pkg.Test
,以下工作正常:
package pkg
package matchers {
object Test {
def unapply(t : Test) : Option[Int] = Some(t.v)
}
}
object main {
import pkg.matchers._
def main(args : Array[String]) {
val t = new Test(1)
t match {case Test(v) => println(v)}
println(t.v)
}
}
更新
Extractor 不需要是伴生对象,这意味着您不需要相应的类。任何object
withunapply
方法都可以用作提取器。
object StringLength {
def unapply(x: String): Option[Int] = Some(x.length)
}
object Main {
def main(args: Array[String]) {
"Hello World" match {
case StringLength(x) => println("length:" + x)
}
}
}
因此,如果 main 方法不在 中pkg
,您有以下选择:
将您的提取器重命名为另一个名称,以便编译器知道您正在使用提取器。
使用 FQN,因此编译器知道您正在访问pkg.matchers.Test
而不是pkg.Test
.
package pkg.matchers {
import pkg._
object Test {
def unapply(t : Test) : Option[Int] = Some(t.v)
}
}
object Main {
def main(args: Array[String]) {
import pkg.Test
val t = new Test(1)
t match {case pkg.matchers.Test(v) => println(v)}
println(t.v)
}
}
使用语法重命名pkg.Test
为另一个名称import
,因此它不会与pkg.matchers.Test
.
object Main {
def main(args: Array[String]) {
import pkg.{Test => JTest}
import pkg.matchers.Test
val t = new JTest(1)
t match {case Test(v) => println(v)}
println(t.v)
}
}
只需从 导入所有内容pkg
,特别是导入pkg.matcher.Test
。
def main(args: Array[String]) {
import pkg._
import pkg.matchers.Test
val t = new Test(1)
t match {case Test(v) => println(v)}
println(t.v)
}