IBM scala(一)-----面对对象的函数编程
2016-07-13 22:50
267 查看
一种可伸缩语言
Scala 是一种函数对象混合的语言,具有一些强大的优点:首先,Scala 可编译为 Java 字节码,这意味着它在 JVM 上运行。除了允许继续利用丰富的 Java 开源生态系统之外,Scala 还可以集成到现有的 IT 环境中,无需进行迁移。
其次,Scala 基于 Haskell 和 ML 的函数原则,大量借鉴了 Java 程序员钟爱的面向对象概念。因此,它可以将两个领域的优势混合在一起,从而提供了显著的优点,而且不会失去我们一直依赖的熟悉的技术。
最后,Scala 由 Martin Odersky 开发,他可能是 Java 社区中研究 Pizza 和 GJ 语言的最著名的人,GJ 是 Java 5 泛型的工作原型。而且,它给人一种 “严肃” 的感觉;该语言并不是一时兴起而创建的,它也不会以同样的方式被抛弃。
函数概念
与许多最近开始在 Java 平台上占有一席之地的动态语言不同,Scala 是静态类型的,正如 Java 代码一样。但是,与 Java 平台不同,Scala 大量利用了类型推断(type inferencing),这意味着,编译器深入分析代码以确定特定值的类型,无需编程人员干预。类型推断需要较少的冗余类型代码。大量的其他函数功能(比如模式匹配)已经被引入到 Scala 语言中,但是将其全部列出超出了本文的范围。Scala 还添加许多目前 Java 编程中没有的功能,比如操作符重载(它完全不像大多数 Java 开发人员所想象的那样), 具有 “更高和更低类型边界” 的泛型、视图等。与其他功能相比,这些功能使得 Scala 在处理特定任务方面极其强大,比如处理或生成 XML。
下面是一段scala版的helloword
object HelloWorld { def main(args: Array[String]) = { System.out.println("Hello, Scala!") } } |
闭包
函数作为一级概念的一个含义是,它们必须被识别为单独的结构,也称为闭包,这是 Java 社区最近一直热烈争论的话题。在 Scala 中,这很容易完成。考虑下面的程序,此程序定义了一个函数,该函数每隔一秒调用一次另一个函数:object Timer { def oncePerSecond()= { while (true) { System.out.println("Time flies when you're having fun(ctionally)...") Thread.sleep(1000) } } def main(args: Array[String]) = { oncePerSecond } |
oncePerSecond方法的主体。传统的 Java 程序员将通过为
oncePerSecond定义
String参数来包含要显示的消息。但甚至这样也是极端受限的:其他任何周期任务(比如 ping 远程服务器)将需要各自版本的
oncePerSecond,这很明显违反了 “不要重复自己” 的规则。我认为我可以做得更好。
object Timer { def oncePerSecond(callback: () => Unit): Unit = { while (true) { callback() Thread.sleep(1000) } } def timeFlies(): Unit = { Console.println("Time flies when you're having fun(ctionally)..."); } def main(args: Array[String]): Unit = { oncePerSecond(timeFlies) } } |
oncePerSecond接受一个参数,但其类型很陌生。形式上,名为
callback的参数接受一个函数作为参数。只要传入的函数不接受任何参数(以 () 指示)且无返回(由 => 指示)值(由函数值 unit 指示),就可以使用此函数。然后请注意,在循环体中,我使用
callback来调用传递的参数函数对象。
幸运的是,我在程序的其他地方已经有了这样一个函数,名为
timeFlies。所以,我从
main中将其传递给
oncePerSecond函数。(您还会注意到,
timeFlies使用了一个 Scala 引入的类
Console,它的用途与
System.out或新的
java.io.Console类相同。这纯粹是一个审美问题;
System.out或
Console都可以在这里使用。)
匿名函数
现在,这个timeFlies函数似乎有点浪费 — 毕竟,它除了传递给
oncePerSecond函数外毫无用处。所以,我根本不会正式定义它,如下图所示:
object Timer |
oncePerSecond,看起来像来自 Lisp 或 Scheme 的 lambda 表达式,事实上,这是另一种闭包。这个匿名函数 再次展示了将函数当作一级公民处理的强大功能,它允许您在继承性以外对代码进行全新地泛化。(Strategy 模式的粉丝们可能已经开始唾沫横飞了。)事实上,
oncePerSecond仍然太特殊了:它具有不切实际的限制,即回调将在每秒被调用。我可以通过接受第二个参数指明调用传递的函数的频率,来将其泛化,如下
所示:
object Timer |
Array类具有一个函数
filter,此函数在下面进行定义
class Array[A] { // ... def filter (p : (A) => Boolean) : Array[A] = ... // not shown }声明
p是一个接受由
A指定的泛型参数的函数,然后返回一个布尔值。Scala 文档表明
filter“返回一个由满足谓词 p 的数组的所有元素组成的数组”。这意味着如果我想返回我的 Hello World 程序,查找所有以字母 G 开头的命令行参数,则可以以下代码:
object HelloWorld { def main(args: Array[String]): Unit = { args.filter( (arg:String) => arg.startsWith("G") ) .foreach( (arg:String) => Console.println("Found " + arg) ) } } |
filter接受谓词,这是一个隐式返回布尔值(
startsWith()调用的结果)的匿名函数,并使用
args中的每个元素来调用谓词。如果谓词返回 true,则它将此值添加到结果数组中。遍历了整个数组之后,它接受结果数组并将其返回,然后此数组立即用作 “foreach” 调用的来源,此调用执行的操作就像它名字的含义一样:
foreach接受另一个函数,并将此函数应用于数组中的每个元素(在本例中,仅显示每个元素)。
不难想象等同于上述
HelloG.scala的 Java 是什么样的,而且也不难发现 Scala 版本非常简短,也非常清晰。
相关文章推荐
- Python 面向对象编程——类和实例
- 模拟键盘输入字符串的C++类
- 模拟键盘向当前光标处发送字符串
- 分割字符串
- 获取多个同名窗口的句柄
- Python + Android + Uiautomator自动化测试
- 基于C语言sprintf函数的深入理解
- struts2 复杂参数封装
- 提高项目31.4-读入一个C++程序,整理其格式,使其按规范排版
- java_reflect_03
- Eclipse中android插件的安装
- 最小化所有窗口(模拟显示桌面)
- 怎样在java虚拟机中理解Java并发
- EnumWindows 传递自定义参数实例
- 生成rdp文件中的密码字串
- Spring入门篇学习笔记(2)
- JAVA回调机制
- Struts2工作原理及流程
- java ssh 框架下 利用junit4 spring-test进行单元测试
- java基础总结