类、字段、方法
类是对象的蓝图,一旦定义了类,就可以用new关键字从蓝图创建对象。
//给出下列定义 class Cat { } //你就能创建Cat对象 object Cat { val cat = new Cat }
在类定义的时候,我们可以设定字段和方法,这也被称作成员。
字段:用 val 或 var 定义,都是指向对象的变量,其中保留了对象的状态或者数据;
方法:用 def 定义,内部包含了可执行代码,使用变量对对象多运算工作。
在实例化类的时候,执行期的环境会设定一些内存来保存对象状态的镜像,即保存变量的内容。例如执行了下列操作
1 //给出下列定义 2 class Cat { 3 var num=0 4 } 5 6 object Cat { 7 val cat1 = new Cat 8 val cat2 = new Cat 9 }
上面代码中,定义了一个类Cat,同时定义了一个var类型的变量num;
然后对这个类进行了两次实例化操作。
对象在内存的镜像大概如下:
如果修改了num的值
1 //给出下列定义 2 class Cat { 3 var num=0 4 } 5 6 //修改cat2的num值 7 object Cat { 8 val cat1 = new Cat 9 val cat2 = new Cat 10 cat2.num=3 11 }
对象在内存的镜像大概如下:
虽然我们定义的:cat1、cat2是 val 类型的,但是里面的变量值的我们是可以修改的,只是你不能在将他们再次赋值为不同的对象,如
1 //给出下列定义 2 class Cat { 3 var num=0 4 } 5 6 //修改cat2的num值 7 object Cat { 8 val cat1 = new Cat 9 val cat2 = new Cat 10 cat2.num=3 11 cat2=new Cat //此处编译不通过 12 }
分号推断
Scala程序中,语句末尾的分号通常是可选的。
如果一行只有一个语句,可写可不写;
如果一行有多个语句,则必须要写。
1 object Cat { 2 val cat1 = new Cat 3 // val cat2 = new Cat 4 // 如果我们要实现 cat1.num+1 5 cat1.num 6 +1 7 // 上面的语句会呗分成两个部分 cat1.num 和 +1 可以采用下面两种的方法将之合成一个整体 8 (cat1.num 9 +1) 10 // 或者 11 cat1.num+ 12 1 13 14 }
用括号将之括起来或者将 “+” 放在行末,实际上,在Scala中,当你使用“+”这种中缀操作符的时候,操作符放在行尾才是Scala的普遍风格。
分号推断规则:
- 疑问行由一个不能合法作为语句结尾的字结束,如句点或上面所示的中缀操作符
- 下一行开始的字是不能作为开始的字
- 行结束于括号 "(...)" 方框 "[...]" 内部,因为这些符号不可能容纳多个语句
上述三点除非有一点成立,否则语句末尾被认为是一个分号。
Singleton 对象(单例对象)
Scala 和 Java 相比,Scaa没有静态成员,而作为替代,Scala有单例对象:Singleton 对象。除了用 object 关键字替换了 class 之外,单例对象的定义就和累的定义一样。
线面定义一个单例对象
1 class ChecksumAccumulator { 2 private var sum = 0 3 4 def add(b: Byte) { 5 sum += b 6 } 7 8 def checksum() = ~(sum & 0xFF) + 1 9 } 10 11 object ChecksumAccumulator { 12 // 注:原文是 val类型的 但是后面的操作 cache += (s -> cs) 相当于重新指向一个新的对象 这是非法的 13 // private val cache = Map[String, Int]() 14 private var cache = Map[String, Int]() 15 16 def calculate(s: String): Int = 17 if (cache.contains(s)) 18 cache(s) 19 else { 20 val acc = new ChecksumAccumulator 21 for (c <- s) 22 acc.add(c.toByte) 23 val cs = acc.checksum() 24 cache += (s -> cs) 25 cs 26 } 27 }
object ChecksumAccumulator 和 class ChecksumAccumulator同名,
object ChecksumAccumulator 称为 class ChecksumAccumulator 的伴生对象:companion object
class ChecksumAccumulator 称为 object ChecksumAccumulator 的伴生类:companion class
类和单例对象的一个差别是:单例对象不带参数,而类可以,因为你不能用 new 关键字实例化一个单例对象,你没机会给它传递参数。
每个单例对象都被作为一个有静态变量指向的虚构类:synthetic class 的一个实例来实现,因此他们和Java的静态类有着相同的初始化语法。
不与伴生类共享名称的单例对象称为孤立对象:standalone object,在某些情况下会有到孤立对象,比如:把相关功能方法集中在一起或者定义一个Scala应用的入口。
注:单例对象会在第一次被访问的时候初始化。
注:你必须在一份源文件里面定义类和他的伴生对象。
Scala 程序
和Java类似,要执行一个Scala程序,需要提供一个包含main方法--一个仅带一个参数Array[String],而且结果类型为 Unit 的单例对象或估计对象名。任何带有合适签名的main方法的单例对象都可以作为程序的入口,如:
1 import ChecksumAccumulator.calculate 2 3 object Summer { 4 def main(args: Array[String]): Unit = { 5 for (arg <- args) { 6 println(arg + ":" + calculate(arg)) 7 } 8 } 9 }
和编译有两个方法:
scalac ChecksumAccumulator.scala Summer.scala
每次编译器启动时,需要花时间扫描jar文件内容。
fsc ChecksumAccumulator.scala Summer.scala
称为快速Scala编译器的后台服务,第一次执行 fsc时,会创建一个绑定你计算机端口上的本地服务后台进程,然后把文件列表通过端口发送到后台进行编译。
下一次执行fsc时,后台进程已经在运行了,所以fsc将只是把文件列表发给后台进程,它会立刻开始编译。
使用 fsc 只需在第一次等待 Java 运行环境启动。然后可以用 fsc -shutdown 来关闭
上面的两个明亮将会创建 Java 类文件,然后可以用 scala 命令运行。此时需要调用包含正确 main 方法签名的单例对象或孤立对象名,如
scala Summer of love
of:-213
love:-182
此为本人 Scala 编程中文版 学习笔记