浅谈Scala 2.8的包对象(package object)
2011-11-15 09:18
549 查看
Scala 2.8提供包对象(package object)的新特性。什么是包对象呢?按我的理解,根据Scala“一切皆对象”设计哲学,包(package)也是一种对象。既然是对象,那么就应该有属性和方法,也可以在包对象内声明某个类型的别名。举个例
可以看到,定义包对象跟定义一个普通的伴随对象(companion object)在写法上的唯一区别就是在关键字object 前加上 package 。
然后我们可以像使用伴随对象那样使用包对象,比如
如果包对象的作用仅仅限于伴随对象那样,那scala 2.8完全没有必要引入这种特性。实际上包对象最重要的用途是兼容旧的类库,或者为某些数据类型提供增强版本。
比如在scala 2.7.7中,List是定义在scala包下的一个不可变集合类。这样做的目的是每次使用List的时候不需要显式地导入包名,因为List是一个使用很频繁的类。
在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.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接口进行了封装和改进:
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 。
然后我们可以像使用伴随对象那样使用包对象,比如
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完全没有必要引入这种特性。实际上包对象最重要的用途是兼容旧的类库,或者为某些数据类型提供增强版本。
比如在scala 2.7.7中,List是定义在scala包下的一个不可变集合类。这样做的目的是每次使用List的时候不需要显式地导入包名,因为List是一个使用很频繁的类。
在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文档或源码,你会发现它定义了一个包对象:
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 // ... }
相关文章推荐
- 浅谈Scala 2.8的包对象(package object)
- 浅谈Scala 2.8的包对象(package object)
- 浅谈Scala 2.8的包对象(package object)
- 浅谈Vue2.2.0源码(一)-- 查询一个object类型对象在一个object数组中的索引
- scala学习13之与trait同名的object对象
- UML系列图——静态图(对象图 Object和包图 Package)
- scala object隐式对象
- 浅谈Scala的Class、Object和Apply()方法
- 【scala 笔记(6)】 类(class)和对象(object)
- Scala错误:object xml is not a member of package scala
- Scala系列学习及应用(Object对象)
- 走进Scala——伴生对象(Companion Object)
- Scala学习教程笔记二之函数式编程、Object对象、伴生对象、继承、Trait、
- scala学习之路:8.staticObject与伴生类伴生对象
- 浅谈Javascript中Object与Function对象
- Scala入门系列(六):面向对象之object
- 走进Scala——伴生对象(Companion Object)<转>
- 浅谈Scala对象构造过程
- Scala伴生类Class和伴生对象Object的区别