5.Scala 类和对象 (二)

前面提到Scala比Java更加面向对象,这是因为Scala不允许类保护静态元素(静态变量或静态方法)。在Scala中提供类似功能的是成为“Singleton(单例对象)“的对象。在Scala中定义Singleton对象的方法除了使用object,而非class关键字外和类定义非常类似,下面例子创建一个ChecksumAccumulator对象:
1

object
ChecksumAccumulator {

2

private
val
cache
=
Map [String, Int] ()

3

def
calculate(s
:
String)
:
Int
=

4

if
(cache.contains(s))

5

cache(s)

6

else
{

7

val
acc
=
new
ChecksumAccumulator

8

for
( c <- s)

9

acc.add(c.toByte)

10

val
cs
=
acc.checksum()

11

cache +

( s -> cs)

12

cs

13

}

14

}

这个对象和上一篇创建的类ChecksumAccumulator同名,这在Scala中把这个对象成为其同名的类的“伴侣”对象(Companion object)。 如果你需要定义的类的companion对象,Scala要求你把这两个定义放在同一个文件中。类和其companion对象可以互相访问对方的私有成员。如果你是Java成员,可以把Singleton对象看成以前Java定义静态成员的地方。你可以使用类似Java静态方法的方式调用Singleton对象的方法,比如下面为这个例子完整的代码:
1

import
scala.collection.mutable.Map

2

class
ChecksumAccumulator{

3

private
var
sum
=
0

4

def
add(b
:
Byte)
:
Unit
=
sum +
=
b

5

def
checksum()
:
Int
=
~ (sum &
0xFF
) +
1

6

}

7

8

object
ChecksumAccumulator {

9

private
val
cache
=
Map [String, Int] ()

10

def
calculate(s
:
String)
:
Int
=

11

if
(cache.contains(s))

12

cache(s)

13

else
{

14

val
acc
=
new
ChecksumAccumulator

15

for
( c <- s)

16

acc.add(c.toByte)

17

val
cs
=
acc.checksum()

18

cache +

( s -> cs)

19

cs

20

}

21

}

22

23

println ( ChecksumAccumulator.calculate(
"Welcome to Scala Chinese community"
))

Scala 的singleton对象不仅限于作为静态对象的容器,它在Scala中也是头等公民,但仅仅定义Singleton对象本身不会创建一个新的类型,你不可以使用new再创建一个新的Singleton对象(这也是Singleton名字的由来),此外和类定义不同的是,singleton对象不可以带参数(类定义参数将在后面文章介绍)。
回过头来看看我们的第一个例子”Hello World“。
1

object
HelloWorld {

2

def
main(args
:
Array[String]) {

3

println(
"Hello, world!"
)

4

}

5

}

这是一个最简单的Scala程序,HelloWorld 是一个Singleton对象,它包含一个main方法(可以支持命令行参数),和Java类似,Scala中任何Singleto对象,如果包含main方法,都可以作为应用的入口点。在这里要说明一点的是,在Scala中不要求public类定义和其文件名同名,不过使用和public类和文件同名还是有它的优点的,你可以根据个人喜好决定是否遵循Java文件命名风格。最后提一下Scala的trait功能,Scala的trait 和Java 的Interface相比,可以有方法的实现(这点有点像抽象类,但如果是抽象类,就不会允许继承多个抽象类)。Scala的Trait支持类和Singleton对象和多个Trait混合(使用来自这些Trait中的方法,而不时不违反单一继承的原则)。Scala为Singleton对象的main定义了一个App trait类型,因此上面的例子可以简化为:
1

object
HelloWorld
extends
App{

2

println(
"Hello, world!"
)

3

}

这段代码就不能作为脚本运行,Scala的脚本要求代码最后以表达式结束。因此运行这段代码,需要先编译这段代码:scalac Helloworld.scala
编译好之后,运行该应用
scala HelloWord
注意: Scala提供了一个快速编译代码的辅助命令fsc (fast scala compliler) ,使用这个命令,只在第一次使用fsc时启动JVM,之后fsc在后台运行,这样就避免每次使用scalac时都要载入相关库文件,从而提高编译速度。

你可能感兴趣的:(5.Scala 类和对象 (二))