Scala 2.8提供包對象(package object)的新特性。什麼是包對象呢?按個人理解,根據Scala「一切皆對象」設計哲學,包(package)也是一種對象。既然是對象,那麼就應該有屬性和方法,也能夠在包對象內聲明某個類型的別名。舉個例 java
package com{ package object ggd543{ type HashMap[A,B] = scala.collection.mutable.HashMap[A,B]; val HashMap = scala.collection.mutable.HashMap def print = println("hello, ggd543") } package object aiguozhe{ var name = "aiguozhe" def sayHello = println("hello") } }
能夠看到,定義包對象跟定義一個普通的伴隨對象(companion object)在寫法上的惟一區別就是在關鍵字object 前加上 package 。程序員
而後咱們能夠像使用伴隨對象那樣使用包對象,好比app
object Test extends Application{ val myMap: com.ggd543.HashMap[String,String]= null; println(com.ggd543.HashMap) println(com.ggd543.print); println(com.aiguozhe.name) com.aiguozhe.name = "AIGUOZHE" println(com.aiguozhe.name) }
若是包對象的做用僅僅限於伴隨對象那樣,那scala 2.8徹底沒有必要引入這種特性。實際上包對象最重要的用途是兼容舊的類庫,或者爲某些數據類型提供加強版本。ide
好比在scala 2.7.7中,List是定義在scala包下的一個不可變集合類。這樣作的目的是每次使用List的時候不須要顯式地導入包名,由於List是一個使用很頻繁的類。ui
在Scala中,包java.lang,包scala和伴隨對象Predef裏的全部數據類型,屬性和方法會被自動導入到每一個Scala文件中
然而另外一方面,List因爲具備不可變的特性,它應該納入scala.collection.immutable包中。所以在scala 2.8中,List被挪到scala.collection.immutable包下里,但這樣一來2.8版本如何兼容2.7.7版本。因而Scala 2.8引入「包對象」這個特性來解決這個問題。若是你查閱Scala 2.8版本的API文檔或源碼,你會發現它定義了一個包對象:scala
package object scala { // Type and value aliases for collection classes type TraversableOnce[+A] = scala.collection.TraversableOnce[A] type Traversable[+A] = scala.collection.Traversable[A] val Traversable = scala.collection.Traversable type Iterable[+A] = scala.collection.Iterable[A] val Iterable = scala.collection.Iterable type Seq[+A] = scala.collection.Seq[A] val Seq = scala.collection.Seq type IndexedSeq[+A] = scala.collection.IndexedSeq[A] val IndexedSeq = scala.collection.IndexedSeq type Iterator[+A] = scala.collection.Iterator[A] val Iterator = scala.collection.Iterator type BufferedIterator[+A] = scala.collection.BufferedIterator[A] type List[+A] = scala.collection.immutable.List[A] val List = scala.collection.immutable.List val Nil = scala.collection.immutable.Nil type ::[A] = scala.collection.immutable.::[A] val :: = scala.collection.immutable.:: type Stream[+A] = scala.collection.immutable.Stream[A] val Stream = scala.collection.immutable.Stream val #:: = scala.collection.immutable.Stream.#:: type Vector[+A] = scala.collection.immutable.Vector[A] val Vector = scala.collection.immutable.Vector type StringBuilder = scala.collection.mutable.StringBuilder type Range = scala.collection.immutable.Range val Range = scala.collection.immutable.Range // Numeric types which were moved into scala.math.* type BigDecimal = scala.math.BigDecimal val BigDecimal = scala.math.BigDecimal type BigInt = scala.math.BigInt val BigInt = scala.math.BigInt type Equiv[T] = scala.math.Equiv[T] type Fractional[T] = scala.math.Fractional[T] type Integral[T] = scala.math.Integral[T] type Numeric[T] = scala.math.Numeric[T] val Numeric = scala.math.Numeric type Ordered[T] = scala.math.Ordered[T] val Ordered = scala.math.Ordered type Ordering[T] = scala.math.Ordering[T] val Ordering = scala.math.Ordering type PartialOrdering[T] = scala.math.PartialOrdering[T] type PartiallyOrdered[T] = scala.math.PartiallyOrdered[T] // others }
也就是說scala.List至關於指向了scala.collection.immutable.List,從而保證升級到Scala 2.8版本不會對原有的程序形成影響。
可能有些讀者會問,經過定義一個伴隨對象scala 可否解決兼容的問題?但細想一下就發現不妥,由於scala包下的一切都要搬到這個伴隨對象scala中去了,這彷佛不太現實。實際上,Scala編譯器會在scala包下建立一個叫package的類,這個類裏面的內容就是package object scala中的東西, scala.List被翻譯成scala.package.List, 但對於程序員來講是透明的 。一樣道理也會在com.ggd543包和com.aiguozhe包下分別建立一個package類.翻譯
有了包對象這個新特性,咱們不但解決了新舊版本的兼容性問題,還能夠對舊的類庫或第三方接口作一些包裝或改進,而不須要額外建立一些類或接口(雖然實際上仍是建立了一個類package,但這是編譯器幫咱們完成的)。好比在Play-scala module的0.8版本(http://www.playframework.org/modules/scala-0.8.zip)中,就對一些JPA接口進行了封裝和改進:設計
import play.data.validation._ import javax.persistence package play { package db { import annotation.target.field package object jpa{ //enums val CascadeType = CascadeTypeWrapper val LockModeType = LockModeTypeWrapper val FetchType = FetchTypeWrapper //classes type Table = persistence.Table type Entity = persistence.Entity type Inheritance = persistence.Inheritance //javax.persistence field type AttributeOverrides = persistence.AttributeOverrides @field type Basic = persistence.Basic @field type Column = persistence.Column @field // ... }