代码之家  ›  专栏  ›  技术社区  ›  Don Mackenzie

包对象

  •  88
  • Don Mackenzie  · 技术社区  · 15 年前

    什么是包对象,与其说是概念,不如说是它们的用法?

    我试着让一个例子发挥作用,我唯一能发挥作用的形式是:

    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 x.y { ... }
    

    也不允许。

    它们常用吗?如果是,怎么做?

    3 回复  |  直到 12 年前
        1
  •  129
  •   Guillaume Massé    10 年前

    通常,您会将包对象放在一个单独的文件中,称为 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

        2
  •  58
  •   Dave Griffith    15 年前

    虽然Moritz的答案是正确的,但还有一点需要注意,包对象就是对象。除此之外,这意味着您可以使用mix-in-inheritance从特性构建它们。莫里茨的例子可以写成

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

    这里的版本控制是一个抽象特性,即包对象必须有一个“version”方法,而jodaalias和javaalias是包含方便类型别名的具体特性。所有这些特性都可以被许多不同的包对象重用。

        4
  •  6
  •   Community CDub    5 年前

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

    不是这样的 斯卡拉3 ,计划于2020年中期发布, based on Dotty ,作为 in here :

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

    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)
    
    推荐文章