副作用 检查前提条件
对于结果类型为Unit的方法,如ChecksumAccumulator的add方法,其执行目的是得到副作用。副作用通常是指改变方法外部的某种状态或者执行I/O的动作。对本例的add方法而言,其副作用是给sum重新赋值。那些仅仅因为其副作用而被执行的方法被称作过程(procedure)。
// 位于ChecksumAccumulator.scala文件中
class ChecksumAccumulator: private var sum = 0 def add(b: Byte): Unit = sum +=
b def checksum(): Int = ~(sum & 0 xFF) + 1
检查前提条件
接下来,我们将注意力转向当前主构造方法的一个问题。本章最开始曾经提到,有理数的分母不能为零。而目前我们的主构造方法接收以参数d传入的零:
scala> Rational(5, 0) // 5/0
val res1: Rational = 5/0
面向对象编程的一个好处是可以将数据封装在对象里,以确保整个生命周期中的数据都是合法的。对Rational这样的不可变对象而言,这意味着需要确保在构造对象时数据合法。由于对于Rational数来说分母为零是非法的状态,因此当0作为参数d传入的时候,不应该允许这样的Rational实例被构建出来。
解决这个问题的最佳方式是对主构造方法定义一个前提条件(precondition),参数d必须为非0值。前提条件是对传入方法或构造方法的值的约束,是方法调用者必须满足的。实现它的一种方式是使用require方法,就像这样:
class Rational(n: Int, d: Int):
require(d != 0)
override def toString = s"$n/$d"
require方法接收一个Boolean类型的参数。如果传入的参数为true,则require方法将会正常返回;否则,require方法将会抛出IllegalArgumentException来阻止对象的构建。