最近开始系统性的学习scala。其实之前使用过scala的,比如我在用Gatling这款性能测试工具的时候就接触到了scala了。Gatling本身就是用Scala写的,而且Gatling的性能测试配置文件本身就是一个scala类,可以随意使用scala甚至是Java提供的各种类库。当时觉得用Gatling特别舒服的原因就在于配置文件强大的表现力。而这种表现力就是由Scala语言提供的。

言归正传,学习Scala还是从最简单的Hello world开始。在Scala官网中显著的标题就是:

Object-Oriented Meets Functional

Have the best of both worlds. Construct elegant class hierarchies for maximum code reuse and extensibility, implement their behavior using higher-order functions. Or anything in-between.

从中可以看出Scala结合了面向对象及函数式编程这两种编程范式。在本文中我将会拿Java语言和其比较,看看到底Scala强在那里。

使用Java语言实现一个Hello World的代码如下:

1
2
3
4
5
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}

以下是Scala的实现:

1
2
3
4
5
object HelloWorld  {
def main(args: Array[String]): Unit = {
println("Hello, World!")
}
}

好吧,如果标点符号不算代码行,Java版本和Scala版本的实现的代码行数是一致的。貌似Scala并没有减少什么。唯一减少的就在于println不用指定类名,以及对main方法不用声明为static。

在这里对Scala实现与Java实现的几个不同之处做个介绍。

  • 第一是Scala对HelloWorld的修饰符使用的是object。其实Scala中也有class关键字,那么object关键字和class关键字有什么区别那?简单来说object关键字定义了一个匿名类,并且创建了该匿名类的单个实例(采用单例模式),该实例名为HelloWorld。所以object中定义的方法自动都是static的。我觉得object关键字存在的价值之一就是建立起了面向对象和函数式的桥梁。因为在面向对象的系统中,所有方法都必须存在于类中,而函数式编程中没有类的概念,使用函数无需new类的实例,所以object中的方法都是静态方法,可以直接被调用。进一步解读请到这里

  • 第二是Scala中对变量的类型的定义方式是变量名在前,类型在后,中间用冒号相隔。原因之一是代码更可读。因为我们更关心变量名,而类型其次,尤其是你拥有一个超级长的类型的情况下(比如
    HashMap<Shape, Pair<String, String>>);原因之二据说是这样的方式在实现Scala类型时技术上要简单些。进一步解读请到这里

  • 第三是main函数的返回值是Unit,而不是Java中的Void。为什么是这样那?我想是因为Scala为了实现自己的类型系统,对于无显式返回值的函数直接使用Void是不合适的。在Scala.Unit文档中是这样定义Unit的:

Unit is a subtype of scala.AnyVal. There is only one value of type Unit, (), and it is not represented by any object in the underlying runtime system. A method with return type Unit is analogous to a Java method which is declared void.

  • 第四是Scala中表达式最后的分号是可选的。原因就是为了契合函数式编程的哲学,即一切尽可能的简单。不写分号程序员一天可以多敲一些代码出来。

好吧,其实在Scala中Hello World还有一种写法。

1
2
3
object HelloWordV2 extends App {
println("Hello, World!")
}

代码从三行减少到了两行,Scala终于胜出了。那么App是个什么鬼?App是一个trait。trait又是什么鬼?trait是Scala中的一个特殊类型,它与Java中的interface很相似,但比interface强大。HelloWordV2添加了对App的扩展后,就自动成为了一个可以运行的程序,由于App中定义了main方法,所以HelloWorldV2中就无需再定义了,牛逼的地方在于HelloWorldV2的body中的代码都会作为main方法中的代码被执行。以下是App源码中对main方法的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@deprecatedOverriding("main should not be overridden", "2.11.0")
def main(args: Array[String]) = { this._args = args for (proc <- initCode) proc() if (util.Properties.propIsSet("scala.time")) { val total = currentTime - executionStart Console.println("[total " + total + "ms]") }

看来App在实现main方法时还设置了一个计时器,通过scala.time这个属性来开关。所以没事翻翻源码还是挺好玩的。

不知有没注意到其实main方法是有个叫args的参数的,那么新版HelloWorld中如何使用该参数那?直接使用它就行。

1
2
3
object HelloWordV2 extends App {
println("Hello, World!" + args(0))
}

ok,Scala版的Hello World就到这里吧。

学习Scala第一篇-从hello World开始的更多相关文章

  1. RabbitMQ学习总结 第一篇:理论篇

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

  2. 学习KnockOut第一篇之Hello World

    学习KnockOut第一篇之Hello World 笔者刚开始学习KnockOut.写的内容就相当于一个学习笔记.且在此处向官网致敬,比较喜欢他们家的Live Example版块,里面有jsFiddl ...

  3. ActionBarSherlock学习笔记 第一篇——部署

    ActionBarSherlock学习笔记 第一篇--部署          ActionBarSherlock是JakeWharton编写的一个开源框架,使用这个框架,可以实现在所有的Android ...

  4. 小白学习VUE第一篇文章---如何看懂网上搜索到的VUE代码或文章---使用VUE的三种模式:

    小白学习VUE第一篇文章---如何看懂网上搜索到的VUE代码或文章---使用VUE的三种模式: 直接引用VUE; 将vue.js下载到本地后本目录下使用; 安装Node环境下使用; ant-desig ...

  5. 前端学习 linux —— 第一篇

    前端学习 linux - 第一篇 本文主要介绍"linux 发行版本"."cpu 架构"."Linux 目录结构"."vi 和 v ...

  6. 我们一起学习WCF 第一篇初识WCF(附源码供对照学习)

    前言:去年由于工作需要我学习了wcf的相关知识,初期对wcf的作用以及为何用怎么样都是一知半解,也许现在也不是非常的清晰.但是通过项目对wcf的运用在脑海里面也算有了初步的模型.今天我就把我从开始wc ...

  7. PHP学习记录第一篇:Ubuntu14.04下LAMP环境的搭建

    最近一段时间会学习一下PHP全栈开发,将会写一系列的文章来总结学习的过程,以自勉. 第一篇记录一下LAMP环境的安装 0. 安装Apache Web服务器 安装之前先更新一下系统 sudo apt-g ...

  8. ASP.NET Core 学习笔记 第一篇 ASP.NET Core初探

    前言 因为工作原因博客断断续续更新,其实在很早以前就有想法做一套关于ASP.NET CORE整体学习度路线,整体来说国内的环境的.NET生态环境还是相对比较严峻的,但是干一行爱一行,还是希望更多人加入 ...

  9. 跟初学者学习IbatisNet第一篇

    写在前面的话:我自己也是一个初学者,写这个专题只是为了对学过知识的巩固,如果有什么不对的地方,欢迎大家指正…………………… 第一篇就简单介绍一下什么是IbatisNet,然后写一个简单的Demo,在后 ...

随机推荐

  1. mysql galera cluster 集群的分裂与仲裁机制

    集群的分裂 当集群由于网络原因分裂为几个单独的组时(一组可能是单节点,也可能是几个互联的节点),数据出现不一致,此时可能产生脑裂及数据不一致.这种情况 下,只有一组节点能够继续提供服务,这组节点的状态 ...

  2. 在ubuntu14.04上部署基于Docker的Gitlab

    首先在一台新的ubuntu上执行更新: sudo apt-get update 然后安装docker(采用国内源) curl -sSL https://get.daocloud.io/docker | ...

  3. linux下搭建nagios

    配置环境:1)CentOS 6.5 作为监控主机,IP:10.0.0.30(根据自己公司需要改变) 2)客户机: windows server  2008R2 , windows 7, windows ...

  4. hdu 1342(DFS)

    Lotto Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  5. JavaScript-BOM-history:保存当前窗口打开后成功访问过的url历史记录栈

    history:保存当前窗口打开后成功访问过的url历史记录栈history.go(n):前进n步前进一步:history.go(1);后退一步:history.go(-1);刷新:history.g ...

  6. 解决 IE 6/7 中console对象兼容性问题

    话不多说,直接上代码 (function (){ //创建空console对象,避免JS报错 if(!window.console) window.console = {}; var console ...

  7. windows里面的批处理命令不停地处理同一条命令

    最近在设置路由表的时候,为了方便,做了一个批处理 route.bat route delete 0.0.0.0route delete 10.25.0.0route ADD 10.25.0.0 MAS ...

  8. TSP旅行商问题的Hopfield求解过程

      连续型Hopfield在matlab中没有直接的工具箱,所以我们们根据Hopfield给出的连续行算法自行编写程序.本文中,以求解旅行商 问题来建立Hopfield网络,并得到解,但是该解不一定是 ...

  9. 《TCP/IP高效编程:改善网络程序的44个技巧》源码在Linux上的编译

    为了先完整编译通过,需要以下几个步骤: 1.进入linux子目录,执行 make.(此步骤为打补丁.) 2.返回上一级目录,打开文件 simplec.c,添加头文件 #include <stdi ...

  10. ProceedingJoinPoint获取当前方法

    aspectJ切面通过ProceedingJoinPoint想要获取当前执行的方法: 错误方法: Signature s = pjp.getSignature();     MethodSignatu ...