Scala单例与伴生对象

Scala比Java更面向对象的一个方面是Scala没有静态成员。替代品是,Scala有单例对象:singleton object。

当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。类和它的伴生对象可以互相访问其私有成员。

定义单例对象不是定义类型(在Scala的抽象层次上说)

类和单例对象间的一个差别是,单例对象不带参数,而类可以。因为你不能用new关键字实例化一个单例对象,你没机会传递给它参数。每个单例对象都被作为由一个静态变量指向的虚构类:synthetic class的一个实例来实现,因此它们与Java静态类有着相同的初始化语法。Scala程序特别要指出的是,单例对象会在第一次被访问的时候初始化。

object AbstractTypeTest1 extends Application {
  def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
    new IntSeqBuffer {
         type T = List[U]
         val element = List(elem1, elem2)
       }
  val buf = newIntSeqBuf(7, 8)
  println("length = " + buf.length)
  println("content = " + buf.element)
}

一个伴生对象的示例:

import scala.collection.mutable.Map 
 
class ChecksumAccumulator { 
    private var sum = 0
            def add(b: Byte) { 
        sum += b 
    } 
 
    def checksum(): Int = ~(sum & 0xFF) + 1
}
 
object ChecksumAccumulator { 
    private val cache = Map[String, Int]() 
    def calculate(s: String): Int = 
    if (cache.contains(s)) 
        cache(s) 
    else { 
        val acc = new ChecksumAccumulator 
        for (c <- s) acc.add(c.toByte) 
        val cs = acc.checksum() 
        cache += (s -> cs) 
        cs 
    } 
}
 
object Summer { 
    def main(args: Array[String]) { 
        println(ChecksumAccumulator.calculate("Every value is an object."))
    }
}

输出为:

-248

但是伴生对象如何体现单例的呢?

class Worker private{
  def work() = println("I am the only worker!")
}
 
object Worker{
  val worker = new Worker
  def GetWorkInstance() : Worker = {
    worker.work()
    worker
  }
}
 
object Job{
  def main(args: Array[String]) { 
        for (i <- 1 to 5) {
          Worker.GetWorkInstance();
        }
    }
}

单例模式就控制类实例的个数,通过伴生对象来访问类的实例就提供了控制实例个数的机会。一个简单示例:

不与伴生类共享名称的单例对象被称为孤立对象:standalone object。最常见的就是程序入口:

class Worker private声明了Worker的首构造函数是私有的,这样Worker的所有构造函数都不能直接被外部调用,因为所有从构造函数都会首先调用其他构造函数(可以是主构造函数,也可以是从构造函数),结果就是主构造函数是类的唯一入口点。

另一方面,Worker.GetWorkInstance();有点类似静态函数调用,但在Scala中这是不对的。Scala会隐式地调用apply来创建一个伴生对象的实例。Scala是一个纯粹的面向对象语言,不允许有任何破坏对象模型的机制存在,比如类的静态变量、函数等。


转载于:https://my.oschina.net/u/1169079/blog/603863

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值