首页 / 软件开发 / JAVA / 面向Java开发人员的Scala指南 - Scala控制结构内部揭密
面向Java开发人员的Scala指南 - Scala控制结构内部揭密2011-01-30Ted NewardScala 是专为 Java™ 平台编写的,因此其语法设计会使 Java 代码编码人员感觉很轻松。同时,Scala 为 JVM 提供了函数语言的固有的强大功能,并以这些函数设计概念为出发点。在这一期的 面向 Java 开发人员的 Scala 指南系列 文章中,Ted Neward 将介绍两种语言之间的细微差异,从一些控制结构(比如 if、while 和 for)开始介绍。正如您将要学习到的那样,Scala 为这些结构提供了一些在其 Java 等效物中无法获得的功能和复杂性。迄今为止,在此 系列 中,我们已经讨论了 Scala 对生态环境的保真度,展示了 Scala 如何将众多的 Java 核心对象功能合并在一起。如果 Scala 只是编写对象的另一种方式,那么它不会有任何引人注意的地方,或者说不再那么功能强大。Scala 的函数概念和对象概念的合并,以及它对编程人员效率的重视,这些使得学习 Scala 语言比 Java-cum-Scala 编程人员所想象的体验更加复杂、更加微妙。例如,对控制结构(比如 if、while 和 for)使用 Scala 的方法。尽管这些控制结构看起来类似一些老的、还比较不错的 Java 结构,但实际上 Scala 为它们增加了一些完全不同的特性。本月的文章是关于使用 Scala 控制结构时能够期望获得哪些东西的入门级读物,而不是在制造许多错误(并编写一堆错误代码)之后,让您冒着遭受挫折的风险去寻找差异。修订后的 Person.scala在 本系列的上一篇文章 中,可以了解到 Scala 能够通过定义一些方法来定义 POJO,这些方法模仿基于 POJO 的环境所需的传统 “getter 和 setter”。在这篇文章发表之后,我收到了 Bill Venners 发来的电子邮件,Bill Venners 是即将发表的正式的 Scala 参考资料使用 Scala 编程(请参阅 参考资料)的合著者之一。Bill 指出了实现上述操作的一个更简单的方法,即使用 scala.reflect.BeanProperty 标注,如下所示:清单 1. 修改后的 Person.scalaclass Person(fn:String, ln:String, a:Int)
{
@scala.reflect.BeanProperty
var firstName = fn
@scala.reflect.BeanProperty
var lastName = ln
@scala.reflect.BeanProperty
var age = a
override def toString =
"[Person firstName:" + firstName + " lastName:" + lastName +
" age:" + age + " ]"
}清单 1 中的方法(上一篇文章 中的清单 13 的修订版)为指定的 var 生成了 get/set 方法对。惟一的缺陷是这些方法并不实际存在于 Scala 代码中,因此其他 Scala 代码无法调用它们。这通常不是什么大问题,因为 Scala 将对为自己生成的字段使用已生成的方法;如果事先不知道,那么这些对您而言可能是一个惊喜。在查看了清单 1 中的代码之后,最让我感到震动的是,Scala 并没有只演示组合函数概念和对象概念的强大威力,它还演示了自 Java 首次发布之后的 30 年里对象语言带来的一些益处。控制是一种幻想您将看到的许多奇怪的、不可思议的东西都可以归功于 Scala 的函数特性,因此,简单介绍一下函数语言开发和演变的背景可能非常有用。在函数语言中,将越来越高级的结构直接构建到语言中是不常见的。此外,语言是通过一组核心原语结构定义的。在与将函数作为对象传递的功能结合之后,可用来定义功能的高阶函数 看起来 像是超出了核心语言的范围,但实际上它只是一个库。类似于任何库,此功能可以替换、扩充或扩展。根据一组核心原语构建语言的合成 特性由来已久,可以追溯到 20 世纪 60 年代和 70 年代使用 Smalltalk、Lisp 和 Scheme 的时候。诸如 Lisp 和 Scheme 之类的语言因为它们在更低级别的抽象上定义更高级别抽象的能力而受到人们的狂热追捧。编程人员可以使用高级抽象,用它们构建更高级的抽象。如今听到讨论这个过程时,它通常是关于特定于域的语言(或 DSL)的(请参阅 参考资料)。实际上,它只是关于如何在抽象之上构建抽象的过程。在 Java 语言中,惟一选择就是利用 API 调用完成此操作;在 Scala 中,可以通过扩展语言本身实现它。试图扩展 Java 语言会带来创建极端场景(corner case)的风险,这些场景将威胁全局的稳定性。而试图扩展 Scala 则只意味着创建一个新库。