温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何在Scala中检查先决条件、添加字段和自指向

发布时间:2021-12-10 08:37:51 来源:亿速云 阅读:135 作者:iii 栏目:编程语言

本篇内容介绍了“如何在Scala中检查先决条件、添加字段和自指向”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

目前主构造器会接受把零传递给d:

scala> new Rational(5, 0)  res6: Rational = 5/0

面向对象编程的一个优点就是它允许你把数据封装在对象之内以便于你确保数据在整个生命周期中是有效的。像Rational这样的不可变对象,这就意味着你必须确保在对象创建的时候数据是有效的(并且,确保对象的确是不可变的,这样数据就不会在之后变成无效的状态)。由于零做分母对Rational来说是无效状态,因此在把零传递给d的时候,务必不能让Rational被构建出来。

解决这个问题的***办法是为主构造器定义一个先决条件:precondition说明d必须为非零值。先决条件是对传递给方法或构造器的值的限制,是调用者必须满足的需求。一种方式是使用require方法,require方法定义在scala包里的孤立对象Predef上。如:

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

require方法带一个布尔型参数。如果传入的值为真,require将正常返回。反之,require将通过抛出IllegalArgumentException来阻止对象被构造。

添加字段

现在主构造器可以正确地执行先决条件,我们将把注意力集中到支持加法。想做到这点,我们将在类Rational上定义一个公开的add方法,它带另一个Rational做参数。为了保持Rational不可变,add方法必须不能把传入的分数加到自己身上。而是必须创建并返回一个全新的带有累加值的Rational。你或许想你可以这么写add:

class Rational(n: Int, d: Int) { // 编译不过   require(d != 0)   override def toString = n +"/"+ d   def add(that: Rational): Rational =    new Rational(n * that.d + that.n * d, d * that.d)  }

很不幸,上面的代码会让编译器提示说:

< console>:11: error: value d is not a member of Rational        new Rational(n * that.d + that.n * d, d * that.d)                                         ˆ  < console>:11: error: value d is not a member of Rational        new Rational(n * that.d + that.n * d, d * that.d)                                                                       ˆ

尽管类参数n和d都在你的add代码可引用的范围内,但是在调用add的对象中仅能访问它们的值。因此,当你在add的实现里讲n或d的时候,编译器将很高兴地提供给你这些类参数的值。但绝对不会让你使用that.n或that.d,因为that并不指向add被调用的Rational对象。实际上,在that指的是调用add的对象时, Rational可以加到自己身上。但是因为你可以传递任何Rational对象给add,所以编译器仍然不会让你说that.n。要想访问that的n和d,需要把它们放在字段中。代码6.1展示了如何把这些字段加入类Rational。

在代码6.1展示的Rational版本里,我们增加了两个字段,分别是numer和denom,并用类参数n和d初始化它们。尽管n和d是用在类的函数体内,因为他们只是用在构造器之内,Scala编译器将不会为它们自动构造域。所以就这些代码来说,Scala编译器将产生一个有两个Int域的类,一个是numer,另一个是denom。我们还改变了toString和add的实现,让它们使用字段,而不是类参数。类Rational的这个版本能够编译通过,可以通过分数的加法测试它:

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

代码 6.1 带字段的Rational

scala> val oneHalf = new Rational(1, 2)  oneHalf: Rational = 1/2 scala> val twoThirds = new Rational(2, 3)  twoThirds: Rational = 2/3 scala> oneHalf add twoThirds  res0: Rational = 7/6

另一件之前不能而现在可以做的事是在对象外面访问分子和分母。只要访问公共的numer和denom字段即可:

scala> val r = new Rational(1, 2)  r: Rational = 1 / 2 scala> r.numer  res7: Int = 1 scala> r.denom  res8: Int = 2

自指向

关键字this指向当前执行方法被调用的对象实例,或者如果使用在构造器里的话,就是正被构建的对象实例。例如,我们考虑添加一个方法,lessThan,来测试给定的分数是否小于传入的参数:

def lessThan(that: Rational) =    this.numer * that.denom <  that.numer * this.denom

这里,this.numer指向lessThan被调用的那个对象的分子。你也可以去掉this前缀而只是写numer;着两种写法是相同的。

举一个不能缺少this的例子,考虑在Rational类里添加max方法返回指定分数和参数中的较大者:

def max(that: Rational) =   if (this.lessThan(that)) that else this

这里,***个this是冗余的,你写成(lessThan(that))也是一样的。但第二个this表示了当测试为假的时候的方法的结果;如果你省略它,就什么都返回不了了。

“如何在Scala中检查先决条件、添加字段和自指向”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI