上一个版本的Rational里,我们只是分别用n初始化了number,用d初始化了denom。结果Rational的分子和分母可能比实际需要的要大。例如有理数66/42,可以简化为11/7。但目前Rational的主构造器没有这个功能。
有理数的简化,需要把分子和分母都除以最大公约数。如:66和42的最大公约数是6。66/42的分子和分母都除以6就产生它的最简形式11/7。见下面这个例子:package scalaTestclass Rational(n:Int,d:Int) { require(d != 0) private val g = gcd(n.abs,d.abs) //注意这里 val number:Int = n/g val denom:Int = d/g def this(n:Int) = this(n,1) override def toString = number + "/" + denom def add(that:Rational):Rational = { new Rational(number * that.denom + that.number * d,d * that.denom) } def lessThan(that:Rational) = { this.number * that.denom < that.number * this.denom } def max(that:Rational) = { if(this.lessThan(that)) that else this } private def gcd(a:Int,b:Int):Int = { //注意这里 if(b == 0) a else gcd(b,a % b) }}这里,我们添加了 私有字段g,并修改了number和denom的初始化。因为g是私有的,所以只能在类的主体之内被访问,外部不可见。我们还添加了 私有方法gcd用来计算传入的两个数的最大公约数。另外,把 private关键字放在 字段或 方法定义之前可以让定义 私有化。 Scala编译器把Rational三个字段的初始化依照它们在源代码中出现的次序放入主构造器。所以g的初始化代gcd(n.abs,d.abs)将在另外两个之前执行,因为它在源文件中出现得最早。g将被初始化为类参数n和d的绝对值的最大公约数,然后再被用于number和denum的初始化。