包对象
什么是包对象,不是这个概念,而是它们的用法?
我试图得到一个工作的例子,我得到的唯一的工作如下:
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
和从Tuple2
到Dimension
隐式转换。
当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别名的具体特征。 所有这些特性都可以被许多不同的包对象重用。