1、类
类是对象的蓝图。在类的定义中,你会填入 字段(field) 和 方法(method), 这些被统称为 成员。
通过 val 或 var 定义的字段是指向对象的变量,通过 def 定义的方法则包含了可执行的代码。字段保留了对象的状态,或者说数据,而方法用数据来对对象执行计算,当你实例化一个类,运行时会指派一些内存来保存对象的状态图。例如,如果你定义一个 ChecksumAccumulator 类并给他一个名为sum的var字段:
class ChecksumAccumulator { var sum = 0 }
然后用如下代码实例化两次:
val acc = new ChecksumAccumulator val caa = new ChecksumAccumulator
2、字段
上面的两个实例中有两个 sum 变量,一个位于 acc 指向的对象里,而另一个位于 csa 指向的对象里。字段又叫作 实例变量,因此每个实例都有自己的变量。acc 本身是 val,由于 acc 和 csa 都是 val 而不是 var,你不能做的是将它们重新赋值指向别的对象。例如,如下代码会报错:
// 不能编译,因为 acc 是一个 val acc = new ChecksumAccumulator
因此你能确信的是,acc 永远指向那个你在初始化时候用的 ChecksumAccumulator 对象,但随着时间的推移,这个对象中包含的字段是有可能变化的。
追求健壮性的一个重要手段是确保对象的状态(它的实例变量值) 在其整个生命周期中都是有效的。通过将字段标记为 私有(private) 来防止外部直接访问字段。因为私有变量只能被定义在同一个类中的方法访问。要将某个字段生命为私有,可以在字段前加上 private 这个访问修饰符。
class ChecksumAccumulator { private var sum = 0; }
有 ChecksumAccumulator 的定义,任何试图通过外部访问 sum 的操作 都会失败:
val acc = new ChecksumAccumulator acc.sum = 5 // 不能编译,因为 sum 是私有的
在 Scala 中,使得成员允许公共访问 (public) 的方式是不在成员前显式的给出任何访问修饰符。换句话说,对于那些在 Java 中可能会用 “public” 的地方,到了 Scala 中,什么都不用加。公共访问是 Scala 的默认访问级别。
3、方法
sum 是私有的变量,唯一可以访问 sum 的代码都定义在类自己里面。因此 ChecksumAccumulator 对于别人来说没有什么用处,除非他定义了一些方法:
class ChecksumAccumulator { private var sum = 0; def add(b: Byte): Unit = { sum +=b; } def checksum(b: Byte): Int = { return ~(sum & 0xFF) + 1; } }
ChecksumAccumulator 现在有两个方法,add 和 checksum,都是函数定义的基本形式。
传递给方法的任何参数都是能在方法里使用的。Scala 方法参数的一个重要特征是他们都是 val 而不是 var。因此如果你在 Scala 的方法里对参数进行重新复制,是不被允许的,将会变异错误。
函数在没有任何 return 的时候,Scala 方法会返回的是该方法计算出的最后一个(表达式的)值。
事实上 Scala 推荐的方法风格是避免使用任何显式的 return 语句,尤其是多个 return 语句。与此相反,尽量将每个方法当做是一个最终交出某个值的表达式。这样的哲学鼓励你编写短小的方法,将大的方法拆分成小的。另一方面,设计中的选择也是取决于上下文的,Scala 也允许你方便的编写有多个显式 return 的方法,如果那确实是你想要的。