包对象

Don*_*zie 89 scala scala-2.8

什么是包对象,而不是概念,但它们的用途?

我试图找一个工作的例子,我开始工作的唯一形式如下:

package object investigations {
    val PackageObjectVal = "A package object val"
}

package investigations {

    object PackageObjectTest {
        def main(args: Array[String]) {
            println("Referencing a package object val: " + PackageObjectVal)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我到目前为止所做的观察是:

package object _root_ { ... }
Run Code Online (Sandbox Code Playgroud)

是不允许的(这是合理的),

package object x.y { ... }
Run Code Online (Sandbox Code Playgroud)

也是不允许的.

似乎必须在直接父包中声明包对象,如果如上所述,则需要包含大括号的包声明表单.

它们是常用的吗?如果是这样,怎么样?

Mor*_*itz 125

通常,您会将包对象放在package.scala与其对应的包中调用的单独文件中.您也可以使用嵌套包语法,但这很不寻常.

包对象的主要用例是,当您使用包定义的API时,需要在包内的各个位置以及包外部进行定义.这是一个例子:

// file: foo/bar/package.scala

package foo

package object bar {

  // package wide constants:
  def BarVersionString = "1.0"

  // or type aliases
  type StringMap[+T] = Map[String,T]

  // can be used to emulate a package wide import
  // especially useful when wrapping a Java API
  type DateTime = org.joda.time.DateTime

  type JList[T] = java.util.List[T]

  // Define implicits needed to effectively use your API:
  implicit def a2b(a: A): B = // ...

}
Run Code Online (Sandbox Code Playgroud)

现在,包内对象中的定义在整个包中可用foo.bar.此外,当该包外部的人导入时,将导入定义foo.bar._.

通过这种方式,您可以阻止要求API客户端发出额外的导入以有效地使用您的库 - 例如,在Scala-swing中您需要编写

import swing._
import Swing._
Run Code Online (Sandbox Code Playgroud)

让所有喜欢善良onEDT和隐式转换Tuple2Dimension.

  • 注意事项:方法重载在包对象中不起作用. (13认同)

Dav*_*ith 56

虽然Moritz的答案很明显,但需要注意的另一件事是包对象是对象.除此之外,这意味着您可以使用混合继承从特征构建它们.莫里茨的例子可以写成

package object bar extends Versioning 
                          with JodaAliases 
                          with JavaAliases {

  // package wide constants:
  override val version = "1.0"

  // or type aliases
  type StringMap[+T] = Map[String,T]

  // Define implicits needed to effectively use your API:
  implicit def a2b(a: A): B = // ...

}
Run Code Online (Sandbox Code Playgroud)

这里Versioning是一个抽象特征,它表示包对象必须有一个"version"方法,而JodaAliases和JavaAliases是包含方便类型别名的具体特征.所有这些特征都可以被许多不同的包对象重用.


Von*_*onC 6

包对象的主要用例是,当您使用包定义的 API 时,您需要在包内以及包外的各个位置进行定义。

Scala 3并非如此,它计划于 2020 年年中发布,基于Dotty,因为在这里

顶级定义

各种定义都可以写在顶层。
不再需要包对象,将被逐步淘汰。

package p 

type Labelled[T] = (String, T) 
val a: Labelled[Int] = ("count", 1) 
def b = a._2 
def hello(name: String) = println(i"hello, $name)
Run Code Online (Sandbox Code Playgroud)