Scala:函数式对象的定义及其使用

简介:

 Scala 中,类(class)的定义比 Java 面相对象的类定义要简洁一些,因为 Scala 在类定义时就同时定义了该类的主构造器(primary constructor。我们知道,构造函数只不过是一种特殊的函数(或称为方法)而已,所以 Scala 中的类定义个人觉得跟方法、函数定义的格式看起来差不多。

 

所谓的函数式对象,其实就是指对象内部没有可变的状态,即类里面的字段都是用关键字 valvalue的意思)定义的。

 

借助《Programming in Scala》中的例子,我们定义一个有理数(Rational)类,在此我们将有理数表示为分数的形式,即1 / 23 / 5的格式。其要求如下:

1  该类的对象(即任意有理数)能够相互之间进行一些基本运算,如加、减、乘、除,此外,还应该能与正数进行这些运算;

2  确保构造出有理数(Rationla 对象)时不能出现分母为零的情况;

3  重写 toString()方法,以最简分数的格式打印出 Rational 对象;

4  可以只给定一个分子来构造有理数,此时我们默认分母为 1,于是需要重载(overload)构造函数,Scala 中称为从构造器

 

看一下实现代码:

 

1.            // 有理数类  

2.            class Rational(n: Int, d: Int){  

3.             

4.                //在构造对象时确保分母不为零  

5.                require(d != 0)  

6.             

7.                // 获得分子分母的最大公约数  

8.                private val g = gcd(n.abs, d.abs)  

9.                val numer: Int = n / g  // 分子  

10.            val denom: Int = d / g  // 分母  

11.         

12.            // 重载构造器,此时的有理数实为整数  

13.            def this(n: Int) = this(n, 1)  

14.         

15.            // 重写toString,必须加上override关键字  

16.            override def toString = {  

17.                if(denom == 1)  

18.                    numer.toString  

19.                else 

20.                    numer + "/" + denom  

21.            }  

22.         

23.            // 常见的add方法  

24.            def add(that: Rational) :Rational = {  

25.                new Rational(  

26.                    numer * that.denom + that.numer * denom,  

27.                    denom * that.denom  

28.                )  

29.            }  

30.              

31.            // 操作符形式的加法  

32.            def +(that: Rational): Rational ={  

33.                new Rational(  

34.                    numer * that.denom + that.numer * denom,  

35.                    denom * that.denom  

36.                )  

37.            }  

38.         

39.            def *(that: Rational): Rational ={  

40.                new Rational(  

41.                    numer * that.numer,  

42.                    denom * that.denom  

43.                )  

44.            }  

45.         

46.            def -(that: Rational): Rational ={  

47.                new Rational(  

48.                    numer * that.denom - that.numer * denom,  

49.                    denom * that.denom  

50.                )  

51.            }  

52.         

53.            def /(that: Rational): Rational ={  

54.                new Rational(  

55.                    numer * that.denom,  

56.                    that.numer * denom  

57.                )  

58.            }  

59.              

60.            // 求倒数的前缀操作符,必须加上unary_修饰 

61.            def unary_~(that: Rational): Rational ={  

62.                new Rational(  

63.                    denom, numer  

64.                )  

65.            }  

66.         

67.            // 递归求分子分母的最大公约数,必须指明结果类型  

68.            private def gcd(a: Int, b: Int): Int =   

69.                if(b == 0) a else gcd(b, a % b)  

70.         

71.            // 有理数的比较:小于  

72.            def lessThan(that: Rational) =  

73.                numer * that.denom < that.numer * denom  

74.         

75.            // 求两数中的较大数  

76.            def max(that: Rational) : Rational =  

77.                //if(lessThan(that)) that else this //省略this也可以  

78.                ifthis lessThan that ) that else this 

79.        

 

 

说明一下代码中的几点,也便于我自己理清Scala 中的编程规范:

1  require(d != 0) Scala 中的方法、主构造器要求调用发必须满足的先决条件,是一种限制,确保了程序的正常运行。看起来功能类似于断言机制,但是 Scala 中也有断言啊,所以我目前还不明白这两者的区别所在。

2  私有的 gcd() 函数是递归函数,必须指明其结果类型(返回类型),它用于求得分子、分母的最大公约数,用于对分数的化简。此外,在 Scala 中,尾递归函数可以被 Scala 编译器进行优化,尽量写尾递归的函数,这才是 Scala 函数式编程偏向的以递归替代while循环的基础。

3  Scala 中的构造器重载使用了 this 关键字,其实是从构造器委托了主构造器的实现

4  add()方法和加号 + 都实现了 Rational 对象(有理数)的加法运算,看起来像是 C++ 中的运算符重载。其实,在 Scala 中并没有操作符的概念,就算是 1 + 2 中的加号,也是一个由Int类型的 1 所调用的函数而已。(说起来,Scala 更像是完全的面向对象语言,至少比 Java 中还存在原始类型要好)当然,我们还可以完整地定义出其他减法sub 函数等等。

5  对于求倒数操作符 ~ ,因为在这里我们将它作为一个前缀操作符,所以必须用 unary_ 修饰,告诉编译器将 ~ 看作前缀操作符。

 

有了上面一系列的函数定义(上面的代码中多是操作符定义),我们就能够进行编写一些脚本代码来测试一下 Rational 类的这些运算了,如下:

 

1.            val a = new Rational(1, 3)  

2.            val b = new Rational(1, 2)  

3.             

4.            println(a add b)  

5.            println(a.add(b))  

6.             

7.            println(a.lessThan(b))  

8.            println(a lessThan b)  

9.             

10.        println(a.max(b))  

11.        println(a max b)  

12.         

13.        val c = new Rational(3)  

14.        println(c)  

15.         

16.        println(new Rational(66, 42))  

17.         

18.        print("1/3 + 1/2 = ")  

19.        println(a + b)  

20.         

21.        print("1/3 - 1/2 = ")  

22.        println(a - b)  

23.         

24.        print("1/3 * 1/2 = ")  

25.        println(a * b)  

26.         

27.        print("(1/3) / (1/2) = ")  

28.        println(a / b) 

 

由于我把上面 Rational 类的定义和这一些针对 Rational 类测试的代码放在同一个 .scala 脚本文件中,并且 Rational 类的代码中有许多中文的注释,所以在使用 scala 命令执行这脚本时需要用选项 –encoding 指定字符集 UTF-8 ,运行结果如下:




本文转自 xxxx66yyyy 51CTO博客,原文链接:http://blog.51cto.com/haolloyin/384387,如需转载请自行联系原作者

相关文章
|
6月前
|
Scala
Scala中的类和对象:定义、创建和使用
Scala中的类和对象:定义、创建和使用
152 1
|
Scala
164 Scala 对象
164 Scala 对象
28 0
|
设计模式 Ubuntu Java
|
Java Scala
scala面向对象编程之类与对象
scala是支持面向对象的,也有类和对象的概念。 示例:定义一个User类,并添加成员变量/成员方法,创建一个Main object,添加一个main方法,并创建Customer类的对象,并给对象赋值,打印对象中的成员,调用成员方法
112 0
scala面向对象编程之类与对象
|
Java 大数据 Scala
大数据开发基础的编程语言的Scala的类和对象
Scala是一种基于JVM的编程语言,它支持面向对象编程和函数式编程。本文将介绍Scala中类和对象的概念和用法,帮助开发者更好地理解和应用这门语言。
72 0
Scala快速入门-6-单例对象及伴生对象
• 用对象作为单例或存放工具方法,Scala没有静态方法或字段 • 类可以有一个同名的伴生对象 • 对象的apply方法通常用来构造伴生类的新实例 • Scala的main函数定义 单例对象
|
Java Scala
Scala快速入门-5-类定义
每个类都有一个主构造器,这个构造器和类的定义“交织”在一起,它的参数直接成为类的字段,主构造器执行类体中所有的语句 类中的字段自动带getter和setter方法 用@BeanProperty注解生成JavaBean的getXxx/setXxx方法 辅助构造器是可选的,它们都叫做this
|
存储 分布式计算 Java
一天学完spark的Scala基础语法教程十、类和对象(idea版本)
一天学完spark的Scala基础语法教程十、类和对象(idea版本)
124 0
一天学完spark的Scala基础语法教程十、类和对象(idea版本)
|
Java 大数据 Scala
scala 对象创建的流程分析|学习笔记
快速学习 scala 对象创建的流程分析。
105 0
|
搜索推荐 关系型数据库 Shell
Scala入门系列终章:类与对象
截至本篇,Scala入门系列即将告一段落,先后用7篇文章将Scala语言的四梁八柱进行了简要介绍,虽然阅读量相较于其他文章更为惨淡,但相信对于有一定编程语言基础又想快速入门Scala的读者来说还是会有一定收获和借鉴的。 本文作为该系列的最后一篇,将重点介绍Scala中类和对象的概念,毕竟Scala也是一门面向对象的编程语言。 坦白讲,个人在学习Scala中这一部分内容时其实也是有些凌乱的,一直觉得未能理解到Scala中类和对象的精髓,所以当下完成此文也仅仅是出于系列内容的完整性,后续也将适时推出其他分享。
173 0
Scala入门系列终章:类与对象