2010-08-03 119 views
75

什麼是包裝物品,不是那麼多概念,而是它們的用法?包裝物品

我試圖得到一個例子工作,我工作的唯一形式如下:

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_ { ... } 

是不允許的(這是合理的),也是不允許的。

看來,一個包對象必須在直接父包中聲明,並且如果按照上面的方式寫入,則需要大括號分隔包聲明表單。

它們是否共同使用?如果是這樣,怎麼樣?

+6

http://www.naildrivin5.com/scalatour/wiki_pages/PackageObjects – oluies 2010-08-04 10:41:44

+1

@Brent,這是一個很好的資源,不僅僅是包對象文章。我聽說過作者,但沒有意識到他會寫這個Scala遊覽,謝謝。 – 2010-08-04 11:45:03

回答

113

通常你把你的包對象在一個單獨的文件,它對應於呼包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客戶端發出額外的導入來有效地使用您的庫 - 例如,在斯卡拉擺動,你需要寫

import swing._ 
import Swing._ 

讓所有善良像onEDT和隱式轉換從Tuple2Dimension

+12

注意事項:方法重載在程序包對象中不起作用。 – retronym 2010-08-04 05:20:11

+0

打敗了我爲什麼選擇將軟件包對象定義在軟件包層次結構的上一層。例如。這意味着如果你希望它屬於你自己的根包,你需要用包對象污染虛擬的'org'或'com'頂層包。 'org.foo'。我發現允許定義直接在它應該是其一部分的包之下 - 將會是稍微適當的語言api界面。 – matanster 2015-10-02 16:22:22

7
+0

@亞瑟克魯斯,謝謝,這似乎表明,他們需要一個單獨的編譯單元(這可能會得到大括號分隔包限制)。問題是我想得到一些可靠的用戶建議,而不是我自己的猜測,關於如何使用它們。 – 2010-08-03 21:33:48

51

雖然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 = // ... 

} 

這裏版本是一個抽象的特質,它說,包對象必須有一個「版本」的方法,而JodaAliases和JavaAliases是包含手持式別名具體特徵。所有這些特徵都可以被許多不同的包對象重用。

+0

整個話題開放很多,似乎已經習慣了它的全部潛力,感謝另一個豐富的例子。 – 2010-08-04 19:05:00

+1

但它們不能用作vals,所以它們不是真正的對象 – 2013-08-08 16:23:04