`

极度诱惑 Scala四大特性你能否抗拒

阅读更多
【IT168 分析】如果你是一名Java程序员,并且关注这编程语言方面的发展,比如经常去TIOBE网站了解编程语言流行度排行,那么你应该听说过Scala,如果你还没有开始学习Scala,或者打算下个礼拜开始学的话,请先看看下面这篇文章,看看能不能改变你的想法。

  Scala是为你准备的吗?你必须自己看明白并做决定。除了伸展性之外,我们发现喜欢用Scala编程实际上还有很多理由。最重要的四个将在本节讨论的方面该是:兼容性,简短,高层级抽象和高级的静态类别。

  Scala是兼容的

  Scala不需要你从Java平台后退两步然后跳到Java语言前面去。它允许你在现存代码中加点儿东西——在你已有的东西上建设——因为它被设计成无缝地与Java实施互操作。Scala程序会被编译为JVM的字节码。它们的执行期性能通常与Java程序一致。Scala代码可以调用Java方法,访问Java字段,继承自Java类和实现Java接口。这些都不需要特别的语法,显式接口描述,或粘接代码。实际上,几乎所有Scala代码都极度依赖于 Java库,而经常无须在程序员意识到这点。

  交互式操作的另一个方面是Scala极度重用了Java类型。Scala的Int类型代表了Java的原始整数类型int,Float代表了float,Boolean代表boolean,等等。Scala的数组被映射到Java数组。 Scala同样重用了许多标准Java库类型。例如,Scala里的字串文本"abc"是java.lang.String,而抛出的异常必须是 java.lang.Throwable的子类。

  Scala不仅重用了Java的类型,还把它们“打扮”得更漂亮。例如,Scala的字串支持类似于toInt和toFloat的方法,可以把字串转换成整数或者浮点数。因此你可以写str.toInt替代 Integer.parseInt(str)。如何在不打破互操作性的基础上做到这点呢?Java的String类当然不会有toInt方法。实际上,Scala有一个解决这种高级库设计和互操作性不相和谐的通用方案。Scala可以让你定义隐式转换:implicit conversion,这常常用在类型失配,或者选用不存在的方法时。在上面的例子里,当在字串中寻找toInt方法时,Scala编译器会发现 String类里没有这种方法,但它会发现一个把Java的String转换为Scala的RichString类的一个实例的隐式转换,里面定义了这么个方法。于是在执行toInt操作之前,转换被隐式应用。

  Scala代码同样可以由Java代码调用。有时这种情况要更加微妙,因为Scala是一种比Java更丰富的语言,有些Scala更先进的特性在它们能映射到Java前需要先被编码一下。
内容导航

  Scala是简洁的

  Scala程序一般都很短。Scala程序员曾报告说与Java比起来代码行数可以减少到1/10。这有可能是个极限的例子。较保守的估计大概标准的 Scala程序应该有Java写的同样的程序一半行数左右。更少的行数不仅意味着更少的打字工作,同样意味着更少的话在阅读和理解程序上的努力及更少的出错可能。许多因素在减少代码行上起了作用。

  首先,Scala的语法避免了一些束缚Java程序的固定写法。例如,Scala里的分号是可选的,且通常不写。Scala语法里还有很多其他的地方省略了东西。比方说,比较一下你在Java和Scala里是如何写类及构造函数的。在Java 里,带有构造函数的类经常看上去是这个样子:

  // 在Java里


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

  class MyClass {

  private int index;

  private String name;

  public MyClass(int index, String name) {

  this.index = index;

  this.name = name;

  }

  }

  在Scala里,你会写成这样:


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

class MyClass(index: Int, name: String)

  根据这段代码,Scala编译器将制造有两个私有成员变量的类,一个名为index的Int类型和一个叫做name的String类型,还有一个用这些变量作为参数获得初始值的构造函数。这个构造函数还将用作为参数传入的值初始化这两个成员变量。一句话,你实际拿到了与罗嗦得多的Java版本同样的功能。Scala类写起来更快,读起来更容易,最重要的是,比Java类更不容易犯错。

  有助于Scala的简洁易懂的另一个因素是它的类型推断。重复的类型信息可以被忽略,因此程序变得更有条理和易读。

  但或许减少代码最关键的是因为已经存在于你的库里而不需要写的代码。Scala给了你许多工具来定义强有力的库让你抓住并提炼出通用的行为。例如,库类的不同方面可以被分成若干特质,而这些有可以被灵活地混合在一起。或者,库方法可以用操作符参数化,从而让你有效地定义那些你自己控制的构造。这些构造组合在一起,就能够让库的定义既是高层级的又能灵活运用。
内容导航

  Scala是高层级的

  程序员总是在和复杂性纠缠。为了高产出的编程,你必须明白你工作的代码。过度复杂的代码成了很多软件工程崩溃的原因。不幸的是,重要的软件往往有复杂的需求。这种复杂性不可避免;必须(由不受控)转为受控。

  Scala可以通过让你提升你设计和使用的接口的抽象级别来帮助你管理复杂性。例如,假设你有一个String变量name,你想弄清楚是否String包含一个大写字符。在Java里,你或许这么写:


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

 // 在Java里

  boolean nameHasUpperCase = false;

  for (int i = 0; i < name.length(); ++i) {

  if (Character.isUpperCase(name.charAt(i))) {

  nameHasUpperCase = true;

  break;

  }

  }

     在Scala里,你可以写成:


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

val nameHasUpperCase = name.exists(_.isUpperCase)

  Java代码把字串看作循环中逐字符步进的低层级实体。Scala代码把同样的字串当作能用论断:predicate查询的字符高层级序列。明显 Scala代码更短并且——对训练有素的眼睛来说——比Java代码更容易懂。因此Scala代码在通盘复杂度预算上能极度地变轻。它也更少给你机会犯错。

  论断,_.isUpperCase,是一个Scala里面函数式文本的例子。它描述了带一个字符参量(用下划线字符代表)的函数,并测试其是否为大写字母。

  原则上,这种控制的抽象在Java中也是可能的。为此需要定义一个包含抽象功能的方法的接口。例如,如果你想支持对字串的查询,就应引入一个只有一个方法hasProperty的接口CharacterProperty:


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

  // 在Java里

  interface CharacterProperty {

  boolean hasProperty(char ch);

  }

  然后你可以在Java里用这个接口格式一个方法exists:它带一个字串和一个

  CharacterProperty并返回真如果字串中有某个字符符合属性。然后你可以这样调用exists:


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

  // 在Java里

  exists(name, new CharacterProperty {

  boolean hasProperty(char ch) {

  return Character.isUpperCase(ch);

  }

  });

  然而,所有这些真的感觉很重。重到实际上多数Java程序员都不会惹这个麻烦。他们会宁愿写个循环并漠视他们代码里复杂性的累加。另一方面,Scala 里的函数式文本真地很轻量,于是就频繁被使用。随着对Scala的逐步了解,你会发现越来越多定义和使用你自己的控制抽象的机会。

  你将发现这能帮助避免代码重复并因此保持你的程序简短和清晰。
内容导航

  Scala是静态类型的

  静态类型系统认定变量和表达式与它们持有和计算的值的种类有关。Scala坚持作为一种具有非常先进的静态类型系统的语言。从Java那样的内嵌类型系统起步,能够让你使用泛型:

  generics参数化类型,用交集:intersection联合类型和用抽象类型:abstract type隐藏类型的细节。这些为建造和组织你自己的类型打下了坚实的基础,从而能够设计出即安全又能灵活使用的接口。

  如果你喜欢动态语言如Perl,Python,Ruby或Groovy,你或许发现Scala把它的静态类型系统列为其优点之一有些奇怪。毕竟,没有静态类型系统已被引为动态语言的某些主要长处。绝大多数普遍的针对静态类型的论断都认为它们使得程序过度冗长,阻止程序员用他们希望的方式表达自己,并使软件系统动态改变的某些模式成为不可能。然而,这些论断经常针对的不是静态类型的  思想,而是指责特定 的那些被意识到太冗长或太不灵活的类型系统。例如,Alan Kay,Smalltalk语言的发明者,有一次评论:“我不是针对类型,而是不知道有哪个没有完痛的类型系统,所以我还是喜欢动态类型。”

  Scala 的类型系统是远谈不上会变成“完痛”。实际上,它漂亮地说明了两个关于静态类型通常考虑的事情(的解决方案):通过类型推断避免了赘言和通过模式匹配及一些新的编写和组织类型的办法获得了灵活性。把这些绊脚石搬掉后,静态类型系统的经典优越性将更被赏识。其中最重要的包括程序抽象的可检验属性,安全的重构,以及更好的文档。

  可检验属性:静态类型系统可以保证消除某些运行时的错误。例如,可以保证这样的属性:布尔型不会与整数型相加;私有变量不会从类的外部被访问;函数带了正确个数的参数;只有字串可以被加到字串集之中。

  不过当前的静态类型系统还不能查到其他类型的错误。比方说,通常查不到无法终结的函数,数组越界,或除零错误。同样也查不到你的程序不符合式样书(假设有这么一份式样书)。静态类型系统因此被认为不很有用而被忽视。舆论认为既然这种类型系统只能发现简单错误,而单元测试能提供更广泛的覆盖,又为何自寻烦恼呢?我们认为这种论调不对头。尽管静态类型系统确实不能替代单元测试,但是却能减少用来照顾那些确需测试的属性的单元测试的数量。同样,单元测试也不能替代静态类型。总而言之,如Edsger Dijkstra所说,测试只能证明存在错误,而非不存在。因此,静态类型能给的保证或许很简单,但它们是无论多少测试都不能给的真正的保证。

  安全的重构:静态类型系统提供了让你具有高度信心改动代码基础的安全网。试想一个对方法加入额外的参数的重构实例。在静态类型语言中,你可以完成修改,重编译你的系统并容易修改所有引起类型错误的代码行。一旦你完成了这些,你确信已经发现了所有需要修改的地方。对其他的简单重构,如改变方法名或把方法从一个类移到另一个,这种确信都有效。所有例子中静态类型检查会提供足够的确认,表明新系统和旧系统可以一样的工作。

  文档:静态类型是被编译器检查过正确性的程序文档。不像普通的注释,类型标注永远都不会过期(至少如果包含它的源文件近期刚刚通过编译就不会)。更进一步说,编译器和集成开发环境可以利用类型标注提供更好的上下文帮助。举例来说,集成开发环境可以通过判定选中表达式的静态类型,找到类型的所有成员,并全部显示出来。

  虽然静态类型对程序文档来说通常很有用,当它们弄乱程序时,也会显得很讨厌。标准意义上来说,有用的文档是那些程序的读者不可能很容易地从程序中自己想出来的。在如下的方法定义中:


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

def f(x: String) = ...

  知道f的变量应该是String是有用的。另一方面,以下例子中两个标注至少有一个是讨厌的:


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

val x: HashMap[Int, String] = new HashMap[Int, String]()

  很明显,x是以Int为键,String为值的HashMap这句话说一遍就够了;没必要同样的句子重复两遍。

  Scala有非常精于此道的类型推断系统,能让你省略几乎所有的通常被认为是讨厌的类型信息。

  在上例中,以下两个不太讨厌的替代品也能一样工作:


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

  val x = new HashMap[Int, String]()

  val x: Map[Int, String] = new HashMap()

  Scala里的类型推断可以走的很远。实际上,就算用户代码丝毫没有显式类型也不稀奇。因此,Scala编程经常看上去有点像是动态类型脚本语言写出来的程序。尤其显著表现在作为粘接已写完的库控件的客户应用代码上。而对库控件来说不是这么回事,因为它们常常用到相当精妙的类型去使其适于灵活使用的模式。这很自然。综上,构成可重用控件接口的成员的类型符号应该是显式给出的,因为它们构成了控件和它的使用者间契约的重要部分。
  
分享到:
评论

相关推荐

    scala高级特性

    匿名函数是在 Scala 中,你不需要给每一个函数命名,没有将函数赋给变量的函数叫做匿名函数。由于 Scala 可以自动推断出参数的类型,所有可以写的跟精简一些。例如: ```scala val f = _ * 2 ``` 将方法转换成函数 ...

    scala3 scala3 scala3 scala3 scala3

    在Scala3中,你可以使用单表达式函数,而无需使用`=&gt;`。例如,`x =&gt; x + 1` 可以直接写为 `(x) + 1`。此外,`def` 和 `val` 的定义现在可以合并,使得函数定义更加紧凑。 模式匹配的增强也是Scala3的重要特性。新的...

    scala sdk scala-2.12.3

    Scala SDK,全称为Scala Software Development Kit,是用于开发Scala应用程序的核心工具集。Scala是一种多范式的编程语言,融合了面向对象和函数式编程的特点,它运行在Java虚拟机(JVM)上,能够充分利用Java生态...

    scala2.12.1Windows镜像包

    Scala是一种强大的多范式编程语言,它融合了面向...总的来说,"scala2.12.1Windows镜像包"是Windows用户开始Scala编程之旅的基础,通过安装这个包,你可以配置好Scala开发环境,进一步探索这个强大而富有表现力的语言。

    最好的scala学习 课件

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性,被广泛应用于大数据处理...通过深入学习和实践,你不仅可以掌握Scala语言,还能有效利用Scala在大数据分析和处理项目中发挥出Spark的强大性能。

    scala-2.12.10.zip

    Scala的语法优雅且富有表达力,它允许开发者使用函数式编程的特性,如高阶函数、柯里化、模式匹配和不可变数据结构,同时保留了面向对象的类、接口和继承。这使得Scala成为处理大数据、并发和分布式计算的理想选择,...

    大数据课程-Scala编程基础-3.Scala面对对象的特性_lk_edit.ppt

    包的命名遵循一定的规则,如只允许数字、字母、下划线和小圆点,并且不能以数字开头,不应使用关键字。推荐的命名规范是小写字母加小圆点,表示公司的层次结构,例如`com.lkyoo.oa.model`。包的主要作用包括区分同名...

    scala学习源代码

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性。这个"scala学习源代码"的压缩包文件很可能包含了用于教学或自我学习Scala编程的基础示例。让我们深入了解一下Scala语言的关键概念和特性。 ...

    windows版scala-2.11.12.zip

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性。Scala运行在Java虚拟机(JVM)上,因此可以充分利用Java生态系统的丰富资源。在这个"windows版scala-2.11.12.zip"压缩包中,包含的是Scala ...

    scala + mybatis 数据库查询

    Scala是一种强大的多范式编程语言,它结合了面向对象和函数式编程的特性。MyBatis则是一款流行的Java持久层框架,主要用于简化数据库操作。在本项目中,"scala + mybatis 数据库查询",我们将探讨如何将Scala与...

    Scala如果你在银行工作你懂得

    总的来说,Scala在银行工作中的应用不仅仅体现在其语言特性上,还在于其能够与现有Java基础设施的无缝集成,以及在处理高并发和大数据分析上的优势。对于希望提升系统性能、降低维护成本和增强代码质量的银行来说,...

    scala-2.11.7 包

    Scala还支持高阶函数、类型推断、柯里化、不可变数据结构等特性,这些都是函数式编程的核心元素。此外,它可以与Java代码无缝集成,这意味着你可以利用已有的Java库和框架。 总的来说,Scala-2.11.7提供了一个强大...

    scala-2.11.12.tgz

    这意味着你可以利用丰富的Java生态系统,同时享受Scala的高级特性。 2. **类型推断**:Scala 2.11引入了更强大的类型推断机制,这让代码更简洁,减少了冗余的类型声明。 3. **更快的编译器**:相比于之前的版本,...

    scala-2.12.10.tgz

    7. 函数式编程:Scala支持高阶函数、闭包和不可变数据结构,这些都是函数式编程的核心特性。这使得编写并发程序更加安全和高效。 8. 面向对象编程:Scala是面向对象的,支持类、接口、继承和多态。它还引入了特质...

    scala实战高清讲解

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性,使得它在处理并发和大数据分析方面表现出色。"Scala实战高清讲解"这本书是学习Scala的宝贵资源,尤其对于那些希望深入理解并提升Scala技能的...

    Scala语法简明教程

    - **面向对象+函数式编程**:Scala融合了面向对象编程和函数式编程的特性,支持类、对象和继承的同时也支持高阶函数、不可变性等函数式编程的核心概念。 - **分布式运行**:Scala设计之初就考虑到了并行和分布式...

    scala-2.7.5.final

    在这个2.7.5版本中,Scala的特性包括但不限于: 1. **类型系统**:Scala具有强类型,但允许类型推断,使得代码更简洁。它还支持高级类型构造,如类型参数、类型成员和类型别名。 2. **函数式编程**:Scala提供了高...

    学习scala好的项目

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性,被广泛应用于大数据处理、分布式计算和Web开发等领域。Spark是基于Scala构建的大数据处理框架,其高性能和易用性使得Scala在大数据领域备受...

    scala-2.12.7.zip

    3. **验证安装**:在终端中输入`scala -version`,如果正确设置,你应该能看到Scala 2.12.7的版本信息。 4. **编写代码**:你可以使用文本编辑器或IDE(如IntelliJ IDEA或Eclipse)编写Scala代码,然后使用`sbt`或`...

Global site tag (gtag.js) - Google Analytics