函数式对象(Scala)

函数式对象

以Rational类为例,以下介绍类参数、构造方法、方法、操作符、私有成员、重写、前置条件检查、重载以及自引用。

不可变对象和可变对象的区别

不可变对象通常比可变对象更容易推理,没有随着时间变化而变化,没有复杂的状态空间。其次,可以自由传递不可变对象。而对于可变对象,在传递之前,需要做保护式的拷贝。不可变对象可以安全地用作哈希表的键。
劣势是不可变对象需要一个大的对象图。

构造Rational类

class Rational(n : Int, d : Int)

可以发现和Java有所不同,其类就能接收参数。而在Java中得有构造方法,构造方法接收参数。

重写实现toString方法

可以通过给Rational类添加toString方法来重写默认的实现。

class Rational(n:Int,d:ing) {
    override def toString = n + "/" + d
}

检查前置条件

对于不可变对象,要确保对象在构建时的合法性。比如有理数不能分母为0。当传入参数d为0时,应该禁止生成对象。
解决这个问题是对主构造方法定义一个前置条件

class Rational (n : Int, d : Int) {
    required(d != 0)
    override def toString = n + "/" + d
}

require方法接收一个boolean参数,传入true,正常返回,传入false,跑出IllegalArgumentException异常

添加字段

定义一个add方法,接收另一个Rational类,为了保持不可变特性,add方法必须创建另一个Rational类,等于这两个Rational类的和。

class Rational (n : Int, d : Int) {
    required(d != 0)
    val numer:Int = n
    val denom:Int = d
    override def toString = n + "/" + d
    def add(that : Rational) : Rational = 
        new Rational(
            numer * that.denom + that.numer * denom,
            denom * that.denom
        )
}

不允许使用that.n和that.d来实现。要访问that的分子和分母,要把它们做成字段。

构造方法

某个类定义多个构造方法。在Scala中,主构造方法之外的构造方法称为辅助构造方法。
比如Rational类只接收一个参数,即分子。分母被预定义为1.

//使用this,即类的主构造方法。
def this(n:Int) = this(n,1)

私有字段和方法

比如对Rational类做正规化,要分子和分母除以最大公约数。

class Rational (n : Int, d : Int) {
    required(d != 0)
    private val g = gcd(n.abs, d.abs)
    val numer:Int = n / g
    val denom:Int = d / g
    def this(n:Int) = this(n,1)
    override def toString = n + "/" + d
    def add(that : Rational) : Rational = 
        new Rational(
            numer * that.denom + that.numer * denom,
            denom * that.denom
        )
    private def gcd(a:Int, b:Int) : Int = 
        if (b==0) a else gcd(b, a % b)
}

定义操作符

将x.add(y)转为x+y。

//加法
def + (that: Rational):Rational = 
    new Rational(
        numer * that.denom + that.numer * denom,
            denom * that.denom
    )
//乘法
def * (that: Rational):Rational = 
    new Rational(
        numer * that.numer,
        denom * that.denom
    )

方法重载

以+为例,右操作元,可能是有理数,也有可能是整数

def + (that: Rational):Rational = 
    new Rational(
        numer * that.denom + that.numer * denom,
            denom * that.denom
    )
def + (i: Int) = 
    new Rational(numer + i * denom, denom)
posted @ 2020-06-14 10:19  Tanglement  阅读(271)  评论(0编辑  收藏  举报