Scala伴生类和伴生对象
单例对象与类同名时,这个单例对象被称为这个类的伴生对象,而这个类被称为这个单例对象的伴生类。伴生类和伴生对象要在同一个源文件中定义,伴生对象和伴生类可以互相访问其私有成员。不与伴生类同名的单例对象称为孤立对象。
看看例子:
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)
println("s:"+s+" cs:"+cs)
cs
}
def main(args: Array[String]) {
println("Java 1:"+calculate("Java"))
println("Java 2:"+calculate("Java"))
println("Scala :"+calculate("Scala"))
}
}
ChecksumAccumulator单例对象有一个方法,calculate,用来计算所带的String参数中字符的校验和。它还有一个私有字段,cache,一个缓存之前计算过的校验和的可变映射。2方法的第一行,“if (cache.contains(s))”,检查缓存,看看是否传递进来的字串已经作为键存在于映射当中。如果是,就仅仅返回映射的值,“cache(s)”。否则,执行else子句,计算校验和。else子句的第一行定义了一个叫acc的val并用新建的ChecksumAccumulator实例初始化它。下一行是个for表达式,对传入字串的每个字符循环一次,并在其上调用toByte把字符转换成Byte,然后传递给acc所指的ChecksumAccumulator实例的add方法。完成了for表达式后,下一行的方法在acc上调用checksum,获得传入字串的校验和,并存入叫做cs的val。下一行,“cache += (s -> cs)”,传入的字串键映射到整数的校验和值,并把这个键-值对加入cache映射。方法的最后一个表达式,“cs”,保证了校验和为此方法的结果。
这里打印的结果是:
s:Java cs:-130
Java 1:-130
Java 2:-130
s:Scala cs:-228
Scala :-228
问题来了,ChecksumAccumulator单例对象是不能new的,但是在代码中出现了val acc = new ChecksumAccumulator,这不是矛盾吗?其实不然,这里new的其实是ChecksumAccumulator单例对象的伴生类,即ChecksumAccumulator类,而伴生类和伴生对象可以互相访问对方的私有成员,所以acc可以访问ChecksumAccumulator单例对象的cache变量。同理,那么第一次测试“Java”字符串的时候,acc实例执行了checksum()方法,接下来并把这个数据存到cache这个val中。在第二次测试“Java”字符串的时候,程序是直接从cache变量中获取到了数据,并返回。
这里也可以看出类和单例对象的一个差别是,单例对象是在第一次访问的时候初始化,不可以new,不能带参数,而类可以new,可以带参数。每个单例对象都被作为由一个静态变量指向的虚构类:synthetic class的一个实例来实现,因此它们与Java静态类有着相同的初始化语法。
参考:《Scala编程》
Scala伴生类和伴生对象的更多相关文章
- Scala入门1(单例对象和伴生类)
一.Hello World程序的执行原理 参考http://blog.csdn.net/zhangjg_blog/article/details/22760957 object HelloWorld{ ...
- Scala学习笔记之伴生对象
所谓伴生对象, 也是一个Scala中的单例对象, 使用object关键字修饰. 除此之外, 还有一个使用class关键字定义的同名类, 这个类和单例对象存在于同一个文件中, 这个类就叫做这个单例对象的 ...
- scala学习-类与对象
类 / 对象 [<快学Scala>笔记] 一.类 1.Scala中的类是公有可见性的,且多个类可以包含在同一个源文件中: class Counter{ private var value ...
- 【scala】类的定义和单例对象
一.类的定义 Scala类的定义跟JAVA中类的定义基本是一样的. 示例 class ChecksumAccumulator{ var sum = 0;//Scala默认关键字为public priv ...
- Scala编程入门---面向对象编程之对象
对象 Object,相当于class单个实例,通常在里面放一些静态的filed或method 第一次调用object方法时候,就会执行object的constructor,也就是Object中不在me ...
- Scala基础:面向对象之对象和继承
对象 object 相当于 class 的单个实例,通常在里面放一些静态的 field 或者 method:在 Scala 中没有静态方法和静态字段,但是可以使用 object 这个语法结构来达到同样 ...
- scala 伴生对象与伴生类
package cn.scala_base.oop.scalaobject import java.security.cert.Extension /** * object的构造器必须是无参的,且且构 ...
- scala学习手记15 - 独立对象和伴生对象
上一节中的单例对象MarkerFactory 就是一个独立对象的例子.尽管它管理着Marker类,但是它并没有关联到任何类上. scala也可以创建关联到类上的对象.这样的对象同类共享同一个名字,这样 ...
- 快学Scala 第九课 (伴生对象和枚举)
Scala没有静态方法和静态字段, 你可以用object这个语法结构来达到同样的目的. 对象的构造器只有在第一次被使用时才调用. 伴生对象apply方法: 类和它的伴生对象可以互相访问私有特性,他们必 ...
随机推荐
- memcache详解
MemCache是一个自由.源码开放.高性能.分布式的分布式内存对象缓存系统,用于动态Web应用以减轻数据库的负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高了网站访问的速度. Me ...
- Python 字符串关键字过滤
问题:把给定字符串中的关键字用与关键字等长的“*”串代替. Solution: 方法1: string 中的 replace 函数 方法2: def censor(text, word): words ...
- 关于EEG参考电极
今天搞ADS1299,里面的BIAS偏置运放原来是设置参考电极的. The input multiplexer has EEG-specific functions for the bias driv ...
- asp.net 把图片压缩成zip之后再进行下载
//这是导出的js方法 function fundaochu() { var data = "keyword=GetImageListdaochu&type=daochu&m ...
- MACOS无限试用Cornerstone的方法
MacOS上Cornerstone用起来还是比较好用的,除了add文件目录时不把底下的文件add上去之外.其实之前用Versions也还可以,奈何太贵,买不起正版,破解版又不好用.Cornerston ...
- Javascript 中的 && 和 || 使用小结
准备两个对象用于下面的讨论. var alice = { name: "alice", toString: function () { return this.name; } }; ...
- python 元组操作
关于元组的常用操作,请参考:http://www.runoob.com/python/python-tuples.html 元组的元素不可修改 ,元组的元素的元素可修改 count(self,valu ...
- java之框架
框架有哪些?C++语言的QT.MFC.gtk,Java语言的SSH,php语言的 smarty(MVC模式),python语言的django(MTV模式)等等设计模式有哪些?工厂模式.适配器模式.策略 ...
- linux, configure --prefix=/有什么用
作用就是指定安装路径不指定prefix,则可执行文件默认放在/usr /local/bin,库文件默认放在/usr/local/lib,配置文件默认放在/usr/local/etc.其它的资源文件放在 ...
- [Linux] VirtualBox - 主机与虚拟机互通 - CentOS
使用VirtualBox的主机与虚拟机相互通信方法: (使用VirtualBox不要使用绿色版的,因为绿色版的没有安装虚拟网卡驱动,所以主机与虚拟机是不能相互通信的,切记) 1.设置已经安装好的操作系 ...