Scala:类和对象

类、字段、方法

类是对象的蓝图,一旦定义了类,就可以用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 编程中文版 学习笔记

 

posted @ 2018-10-30 19:26  lillcol  阅读(418)  评论(0编辑  收藏  举报