包对象

什么是包对象,不是这个概念,而是它们的用法?

我试图得到一个工作的例子,我得到的唯一的工作如下:

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) } } } 

我到目前为止的观察结果是:

 package object _root_ { ... } 

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

 package object xy { ... } 

也被禁止。

看来,一个包对象必须在直接父包中声明,如果按照上面的方式写,则需要用括号分隔的包声明表单。

他们是共同使用? 如果是这样,怎么样?

通常情况下,你会把你的包对象放在一个名为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 = // ... } 

现在,该包对象中的定义在整个包foo.bar中可用。 此外,当该包之外的某人导入foo.bar._时,定义会被导入。

这样可以防止要求API客户端发出额外的导入来有效地使用你的库 – 例如在scala-swing中你需要编写

 import swing._ import Swing._ 

拥有所有的好处,比如onEDT和从Tuple2Dimension隐式转换。

当Moritz的回答是现货时,另外要注意的是包对象是对象。 除此之外,这意味着您可以使用混合inheritance来构build特性。 莫里茨的例子可以写成

 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 = // ... } 

这里的Versioning是一个抽象的特征,它说包对象必须有一个“版本”方法,而JodaAliases和JavaAliases是包含方便的types别名的具体特征。 所有这些特性都可以被许多不同的包对象重用。