一、函数式对象

1.1  rational类的规格和创建

  • Rational类来源于有理数(rational number),来表示n(分子)/d(分母)的数字,同时对有理数的运算(加减乘除)建模,还具备归元化的特点。

下例子没有建模的:

scala> val oneHalf=new Rational(1,2)
oneHalf: Rational = 1/2
scala> val twoThirds=new Rational(2,3)
twoThirds: Rational = 2/3
scala> (oneHalf /7)+(1 twoThirds)
<console>:13: error: value / is not a member of Rational
(oneHalf /7)+(1 twoThirds)
^
<console>:13: error: value twoThirds is not a member of Int
(oneHalf /7)+(1 twoThirds)
scala> (oneHalf /7)+1
<console>:13: error: value / is not a member of Rational
(oneHalf /7)+1

  

  • Rational的创建,类名后的括号里的n、d两个类参数。Scala编译器会收集这两个类参数并创造出带同样的参数的主构造器
Class Rational(n:Int,d:Int)
scala> class Rational(n:Int,d:Int){
| println("Created"+n+"/"+d)
| }
defined class Rational scala> new Rational(1,2)
Created1/2
res21: Rational = Rational@6fbfd6ed

默认情况下,Rational类继承了java.lang.Object类的toString实现,只会打印类名、@和十六进制数。

  • 为了打印出具体的分子分母,可以通过重载Rational类的toString实现。
scala> class Rational(n:Int,d:Int){
| override def toString = n+"/"+d }
defined class Rational scala> val x =new Rational(1,3)
x: Rational = 1/3

  

1.2   rational先决条件

面向对象编程的优点之一是它允许你将数据封装在对象之内以确保数据在整个生命周期中的有效性。意味着必须确保rational类建有理数的有效性,

即分母不为0,故应该为主构造器定义一个先决的条件,说明d不为0,先决条件是对传递给方法或者构造器的值的限制,是调用者必须满足的需求。

  • 一种方法是使用require方法,如:
scala> class Rational(n:Int,d:Int){
| require(d!=0)
| override def toString = n+"/"+d
| }
defined class Rational scala> new Rational(2,0)
java.lang.IllegalArgumentException: requirement failed
at scala.Predef$.require(Predef.scala:268)
... 29 elided scala> new Rational(2,9)
res13: Rational = 2/9

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

1.3  添加字段

为了保持Rational的不可变性,add方法不能把传入的有理数加到自己身上,而是必须创建并返回全薪的Rational累加值。

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

  

1.4  自指向this

关键字this指向当前执行方法被调用的对象实例,或者如果使用在构造器里的话,就是正被构建的对象实例。如下:

scala> class Rational(n:Int,d:Int){
| require(d!=0)
| val number:Int=n
| val denom:Int=d
| override def toString =number + "/"+denom
| def add(that:Rational):Rational=
| new Rational(
| number*that.denom+that.number*denom,
| denom*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
| }
defined class Rational scala> new Rational(1,2)
res42: Rational = 1/2
scala> new Rational(1,4)
res43: Rational = 1/4
scala> res43.lessThan(res42)
res44: Boolean = true
scala> res43.max(res42)
res45: Rational = 1/2

  

1.5  辅助构造器

  • Scala里主构造器之外的构造器被称为辅助构造器。作用:对5/1,能够写成Rational(5),这就需要给Rational添加辅助构造器预先设置分母为1
class Rational(n:Int,d:Int){
require(d!=0)
val number:Int=n
val denom:Int=d
def this(n:Int) =this(n,1)//辅助构造器 override def toString =number + "/"+denom
def add(that:Rational):Rational=
new Rational(
number*that.denom+that.number*denom,
denom*that.denom
)
}

  

1.6  私有字段和方法

  • 为了约简化(归元化)为无差别的最简形式,即(66/42---->11/7),引入私有的最大公约数的字段和方法。
 class Rational(n:Int,d:Int){
require(d!=0)
private val g =gcd(n.abs,d.abs)
val number=n/g
val denom=d/g
def this(n:Int) =this(n,1)
def add(that:Rational):Rational=
new Rational(
number*that.denom+that.number*denom,
denom*that.denom
)
override def toString =number + "/"+denom
private def gcd(a:Int,b:Int):Int =
if(b==0) a else gcd(b,a%b)
} scala> new Rational(99,66)
res23: Rational = 3/2

  

17. 定义操作符

在Scala中用常用的数学符号+替换add方法,因为Scala里+是合法的标识符,能够用+定义方法名。

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

  

结果如下:

scala> new Rational(4,9)
res30: Rational = 4/9
scala> new Rational(4,8)
res31: Rational = 1/2
scala> res30+res31
res32: Rational = 17/18

  

1.8. 方法重载

在上面定义的都是有理数的运算,引入整数和有理数之间的运算,使用方法重载。

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

  

结果如下:

scala> new Rational(1,2)
res37: Rational = 1/2
scala> 2
res38: Int = 2
scala> res37+res38
res39: Rational = 5/2

  

最新文章

  1. Reporting Service 告警&quot;w WARN: Thread pool pressure. Using current thread for a work item&quot;
  2. 微信自定义菜单view类型获取openid访问网页
  3. myeclipse自动排版
  4. mac工具收藏
  5. ubuntu 16.04 U盘多媒体不自动弹出
  6. 解决VS2010无法打开,提示无法找到atl100.dll的方法
  7. [原创]java WEB学习笔记72:Struts2 学习之路-- 文件的上传下载,及上传下载相关问题
  8. httpsClient抓取证书
  9. 求高精度幂(java)
  10. Eclipse用法和技巧九:自动添加try/catch块2
  11. java String/StringBuilder 方法
  12. CMDB服务器管理系统【s5day87】:需求讨论-设计思路
  13. 十二、Decorator 装饰器模式
  14. 瀑布流之ajax
  15. Win7 VS2015环境编译cegui-0.8.5
  16. Android 安装时报错INSTALL_FAILED_NO_MATCHING_ABIS 的解决办法
  17. Yum安装Zabbix4.2.0
  18. MySQL-死锁查询
  19. Spring3 访问静态资源
  20. mysql如何优化插入记录速度

热门文章

  1. Python--day23--面向对象思想求正方形面积
  2. tomcat access日志
  3. 浅谈集合框架四——集合扩展:集合循环输出方式及list输出方式的效率对比
  4. Activiti - 新一代的开源 BPM 引擎
  5. H3C 单区域OSPF配置示例一(续)
  6. Character.digit()的意义
  7. POJ 1236 Network of Schools(tarjan)
  8. VC++ CMsflexgrid 使用
  9. vue 父组件中调用子组件函数
  10. CF1151FSonya and Informatics