scala学习-介绍scala的几种特性7

来源:互联网 发布:战斗机模型数据 编辑:程序博客网 时间:2024/04/29 21:41

承接上篇,前提条件检查,使用require。
1添加成员变量
记得上篇的时候,使用了类参数的方式来构建主构造函数,但是这是由缺陷的。
现在我们构建一个两个rational相加的操作。

class Rational (n:Int,d:Int){  println("i am a class construction~"+n+"/"+d)  require(d!=0)  override def  toString = n+"/"+d  def add(that:Rational):Rational = {    new Rational (n*that.d + that.n*d,d*that.d)  }}

这里写图片描述
这里编译都通不过的,为什么呢?在新定义的方法add中,是可以访问n和d的。但是对于that来说,无法使用that.d来访问d,因为that不再定义的类的访问范围之类。这也表明,d和n不能作为类Rational的成员变量,这是要定义成员变量了。做如下修改:

class Rational (n:Int,d:Int){  println("i am a class construction~"+n+"/"+d)  require(d!=0)  val num=n  val denom=d  override def  toString = n+"/"+d  def add(that:Rational):Rational = {    new Rational (n*that.denom + that.num*d,d*that.denom)  }}

注意下的是,这里我们使用了val,因为我们要实现的是immutable的类定义。还有就是num,denom都用定义类型,其实add也不用,但是个人喜欢定义出来,方便阅读。
2引用自身
Scala中也可以使用this,和java的使用方式是一样的,是代表当前的对象,比如实现一个Rational是否小与另一个。

def lessthan(that:Rational)={    this.num*that.denom<that.num*this.denom  }  def lessthan2(that:Rational)={    num*that.denom<that.num*denom  }

3辅助构造函数
以前我们说过,主构造函数,而且除了方法,整个类都会运行一次。除了主构造函数之外的构造函数,都叫做辅助构造函数。
这里定义一个Rational的辅佐构造函数,scala构造辅佐构造函数的语法为this(),且所有辅佐构造函数的语法都是这样。
所有辅佐构造函数的第一个语句都要调用其他的构造函数,不论是辅助构造函数还是主构造函数,这样设计的原因是,一个构造函数最后都会调用到主构造函数,使得主构造函数成为创建类对象的一个单一入口。提高一致性。
4私有成员和私有方法
和java一样都是使用private来修饰的,含义都是一样的。下面定义一个私有方法,求分子分母的最大公倍数。

class Rational (n:Int,d:Int){  println("i am a class construction~"+n+"/"+d)  require(d!=0)    private val g = gcd(n,d)  val num=n/g  val denom=d/g  override def  toString = n+"/"+d  def add(that:Rational):Rational = {    new Rational (n*that.denom + that.num*d,d*that.denom)  }  def lessthan(that:Rational)={    this.num*that.denom<that.num*this.denom  }  def lessthan2(that:Rational)={    num*that.denom<that.num*denom  }  def this (n:Int)={    this(n,1)   }    private def gcd(a:Int,b:Int):Int =     if(b==0) a else gcd(b, a % b)}

自身调用自身,一定要加返回类型,其实,习惯还是加返回类型把,减少错误。还有要注意一点,scala中是按照顺序来初始化变量的,所以g变量要放在Num和denom之前。
5定义运算符
以前我们说过,在scala中运算符其实也就是一个方法而已,没有什么特殊,在上面的列子中,我们定义了一个add方法,你可以x.add(y),也可以x add y,使用,但是我们还可以直接使用+,-来做操作。

def +(that:Rational)={        new Rational (n*that.denom + that.num*d,d*that.denom)     }

这里写图片描述
这里的”i am a class^^”运行了3次,是因为new Rational了三次,运行了里面的println方法。
可以使用相同的方式扩展-,/,*等运算符的用法。
6标识符
其实和java比较相似,字符数据和符号,字符或者以下划线开始。符号的话,避免使用$符号,这是scala在编译时,有些时候要使用的,所以我们避免使用。其实习惯还是以字符开始,做了那么久项目还没遇见过以符号开始的规范。还是以驼峰结构。
这里写图片描述
还有这种混合的,字符和符号
7方法重载
和java一样,重载就是方法名相同,参数不同,假如我想,一个Rational可以和一个Int相加。可以这样

def +(that:Int)={    new Rational(num+that*denom,denom)  }```

val x = new Rational(2,1)
println(x+5)
“`
和java是一样的。
8隐式类型转换-这个比较重要
我们刚才定义了rational+Int,可以解决x+2的问题,但是如果是2+x呢,因为2是Int类型,Int类型没有支持相加的方法?这怎么办?1修改Int源码,加重载其+方法(想想也不可能用这种方法)。2通过静态扩展方法来实现,就是隐式类型转换。就是如果遇到2+x这种情况,Int没有这种方法,就把这个Int类型的实列转换成Rational类型。
scala中是通过implicit def来定义。
这里写图片描述
在eclipse中和教程说的不一样,我晕了个去了……是怎么回事呢?
但是在命令行环境是可以的。我个人觉得是这么回事,eclipse的编译scala的问题。原本编译器看见z+x的时候,发现Int没有+Rational的方法,它是要报错的,但是在它报错之前,会检测当前的作用域,发现了intToRational的方法,所以把它编译成了intToRational(z)+x。
估计eclipse编译的时候,有问题,所以才回出现这种情况。以后在研究下。
隐含类型转换在scala编程中,十分重要。

0 0