领略Scala的函数式对象,本章内容:
通过一个例子展现以内容
1、主构造器和辅构造器
2、重写toString方法和方法的重载
3、检查先决条件
4、自指向
5、隐式转换
呈现方式:
1、叙述表示
2、代码表示
叙述表示
基于下面事例代码的层次叙述。
- 主构造器跟在类名后面,辅构造器展现方式如
def this(n: Int) = this(n, 1)
- 与Java类似,若无重写,解释器打印实例为
Rational@a0b0f5
- require()方法入参为以Boolean类型,如果传入是真,
require()
正常返回。反之抛出异常,阻止对象被构造。如果按照Java的模式来的话,这个方法应该位于构造器内,因为它是用来阻止对象创建的。 - 自指向即
this
,与Java类似 - 隐式转换,
val r = new Rational(2,3)
,r*2
和2*r
是完全不同的,因为由于Scala的运算是调用方法,前者等于r.*2
,而Int类中并没有入参为Raitonal类型的*
运算方法。implicit def intToRational(x: Int): Rational = new Rational(x)
中implicit
关键字告诉Scala编译器,在一些情况下,将Int类型转换到Rational类型。隐式转换把库变得非常灵活和更加方便。不过正因为它强大而往往被误用。
/**
* @author wangzha
* 模拟计算器类
*/
class Rational(n: Int, d: Int) {
require(d != 0)
override def toString: String = numer + "/" + denom
def add(that: Rational): Rational = new Rational(n* that.d+ d* that.n, d* that.d) //编译错误 ①
}
注意上面这一小段代码中,①处编译错误。这是由于尽管n,d入参都在add代码的可引用范围内,但是add方法仅能访问调用对象自身的值
。当add实现访问n或者d的时候,编译器可以给你提供这些参数,即this.n或this.d(自引用)。但是that是无法访问的,因为它不是调用者。解决办法如下:
/**
* @author wangzha
* 模拟计算器类
*/
class Rational(n: Int, d: Int) {
require(d != 0)
override def toString: String = numer + "/" + denom
val numer: Int = n
val denom: Int = d
def add(that: Rational): Rational = new Rational(numer * that.denom + denom * that.numer, denom * that.denom)
}
代码表示
/**
* @author wangzha
* 模拟计算器类
*/
class Rational(n: Int, d: Int) {
//3、检查先决条件
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer: Int = n / g
val denom: Int = d / g
//2、重写toString方法
override def toString: String = numer + "/" + denom
//1、辅助构造器
def this(n: Int) = this(n, 1)
//4、自指向
def add(that: Rational): Rational = new Rational(numer * that.denom + denom * that.numer, denom * that.denom)
private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
/**
* 自定义操作符
*
* @param i
* @return
*/
def +(i: Int): Rational = {return new Rational(numer + i * denom, denom)}
def +(rational: Rational): Rational = {return new Rational(numer * rational.denom + rational.numer * denom, denom * rational.denom)}
//2、方法重载
def -(rational: Rational): Rational = {return new Rational(numer * rational.denom - rational.numer * denom, denom * rational.denom)}
def -(i: Int): Rational = {return new Rational(numer - i * denom, denom)}
def *(rational: Rational): Rational = {return new Rational(numer * rational.numer, denom * rational.denom)}
def *(i: Int): Rational = {return new Rational(numer * i, denom)}
def /(rational: Rational): Rational = {return new Rational(numer * rational.denom, denom * rational.numer)}
def /(i: Int): Rational = {return new Rational(numer, i * denom)}
//5、隐式转换
//implicit告诉编译器可以在一些情况下自动调用,要注意范围,要想Int被调用需要直接定义在解释器里
implicit def intToRational(x: Int): Rational = new Rational(x)
}