3.Scala 进一步

本篇继续上一篇对Scala的整体介绍,本篇进一步解释Scala的一些高级特性,当你学完本篇后,就有足够的知识编写一些实用的Scala脚本应用了。

第七步:使用类型参数化数组

在Scala中你可以使用new来实例化一个类。当你创建一个对象的实例时,你可以使用数值或类型参数。如果使用类型参数,它的作用类似Java或.Net的Generic类型。所不同的是Scala使用方括号来指明数据类型参数,而非尖括号。比如

1valgreetStrings=newArray[String](3)

2greetStrings(0)="Hello"

3greetStrings(1)=","

4greetStrings(2)="world!\n"

5for(i <-0to2)

6print(greetStrings(i))

可以看到Scala使用[]来为数组指明类型化参数,本例使用String类型,数组使用()而非[]来指明数组的索引。其中的for表达式中使用到 0 to 2 ,这个表达式演示了Scala的一个基本规则,如果一个方法只有一个参数,你可以不用括号和. 来调用这个方法。

因此这里的 0 to 2, 其实为(0).to(2) 调用的为整数类型的 to方法,to方法使用一个参数。Scala中所有的基本数据类型也是对象(和Java不同),因此0 可以有方法(实际上调用的是RichInt的方法),这种只有一个参数的方法可以使用操作符的写法(不用.和括号),实际上Scala中表达式 1+2 ,最终解释为(1).+(2) +也是Int的一个方法,和Java不同的是,Scala对方法的名称没有太多的限制,你可以使用符合作为方法的名称。

这里也说明为什么Scala中使用()来访问数组元素,在Scala中,数组和其它普遍的类定义一样,没有什么特别之处,当你在某个值后面使用()时,Scala将其翻译成对应对象的apply方法。因此本例中greetStrings(1) 其实调用greetString.apply(1)方法。这种表达方法不仅仅只限于数组,对于任何对象,如果在其后面使用(),都将调用该对象的apply方法。同样的如果对某个使用()的对象赋值,比如:

1greetStrings(0)="Hello"

Scala将这种赋值转换为该对象的update 方法, 也就是 greetStrings.update(0,”hello”). 因此上面的例子,使用传统的方法调用可以写成:

1valgreetStrings=newArray[String](3)

2greetStrings.update(0,"Hello")

3greetStrings.update(1,",")

4greetStrings.update(2,"world!\n")

5for(i <-0to2)

6print(greetStrings.apply(i))

从这点来说,数组在Scala中并不某种特殊的数据类型,和普通的类没有什么不同。

不过Scala还是提供了初始化数组的简单的方法,比如什么的例子数组可以使用如下代码:

1valgreetStrings=Array("Hello",",","World\n")

这里使用()其实还是调用Array类的关联对象Array的apply方法,也就是

1valgreetStrings=Array.apply("Hello",",","World\n")

第八步: 使用Lists

Scala也是一个面向函数的编程语言,面向函数的编程语言的一个特点是,调用某个方法不应该有任何副作用,参数一定,调用该方法后,返回一定的结果,而不会去修改程序的其它状态(副作用)。这样做的一个好处是方法和方法之间关联性较小,从而方法变得更可靠和重用性高。使用这个原则也就意味着就变量的设成不可修改的,这也就避免了多线程访问的互锁问题。

前面介绍的数组,它的元素是可以被修改的。如果需要使用不可以修改的序列,Scala中提供了Lists类。和Java的List不同,Scala的Lists对象是不可修改的。它被设计用来满足函数编程风格的代码。它有点像Java的String,String也是不可以修改的,如果需要可以修改的String对像,可以使用StringBuilder类。

比如下面的代码:

1valoneTwo=List(1,2)

2valthreeFour=List(3,4)

3valoneTwoThreeFour=oneTwo:::threeFour

4println (oneTwo +" and "+ threeFour +" were not mutated.")

5println ("Thus, "+ oneTwoThreeFour +" is a new list")

定义了两个List对象oneTwo和threeFour ,然后通过:::操作符(其实为:::方法)将两个列表链接起来。实际上由于List的不可以修改特性,Scala创建了一个新的List对象oneTwoThreeFour来保存两个列表连接后的值。

List也提供了一个::方法用来向List中添加一个元素,::方法(操作符)是右操作符,也就是使用::右边的对象来调用它的::方法,Scala中规定所有以:开头的操作符都是右操作符,因此如果你自己定义以:开头的方法(操作符)也是右操作符。

如下面使用常量创建一个列表:

1valoneTowThree=1::2::3::Nil

2println(oneTowThree)

调用空列表对象Nil的 ::方法 也就是

1valoneTowThree=Nil.::(3).::(2).::(1)

Scala 的List类还定义其它很多很有用的方法,比如 head, last,length, reverse,tail 等这里就不一一说明了,具体可以参考List的文档。

第九步:使用元组(Tuples)

Scala 中另外一个很有用的容器类为Tuples,和List不同的Tuples可以包含不同类型的数据,而List只能包含同类型的数据。Tuples在方法需要返回多个结果时非常有用。(Tuple对应到数学的矢量的概念)。

一旦定义了一个元组,可以使用._和索引来访问员组的元素(矢量的分量,注意和数组不同的是,元组的索引从1开始)

1valpair=(99,"Luftballons")

2println(pair._1)

3println(pair._2)

元祖的实际类型取决于它的分量的类型,比如上面pair的类型实际为 Tuple2[Int,String],而 (‘u’,’r’,”the”,1,4,”me”)的类型为Tuple6[Char,Char,String,Int,Int,String].

目前Scala支持的元祖的最大长度为22.如果有需要,你可以自己扩展更长的元祖。

第十步: 使用Sets和Maps

Scala语言的一个设计目标是让程序员可以同时利用面向对象和面向函数的方法编写代码,因此它提供的集合类分成了可以修改的集合类和不可以修改的集合类两大类型。比如Array总是可以修改内容的,而List总是不可以修改内容的。类似的情况,Scala也提供了两种Sets和Map集合类。

比如Scala API 定义了Set的基Trait类型Set(Trait的概念类似于Java中的Interface,所不同的Scala中的Trait可以有方法的实现),分两个包定义Mutable(可变)和Immutable(不可变),使用同样名称的子Trait。下图为Trait和类的基础关系:

使用Set的基本方法如下:

1varjetSet=Set ("Boeing","Airbus")

2jetSet +="Lear"

3println(jetSet.contains("Cessna"))

缺省情况Set为Immutable Set,如果你需要使用可修改的集合类(Set类型),你可以使用全路径来指明Set,比如 scala.collection.mutalbe.Set 。

Scala提供的另外一个类型为Map类型,Scala也提供了Mutable和Immutable 两种Map 类型

Map的基本用法如下(Map类似于其它语言中的关联数组如PHP)

1valromanNumeral=Map (1->"I",2->"II",

23->"III",4->"IV",5->"V")

3println (romanNumeral(4))

第十一步: 学习识别函数编程风格

Scala语言的一个特点是支持面向函数编程,因此学习Scala的一个重要方面是改变之前的指令式编程思想(尤其是来自Java或C#背景的程序员),观念要想函数式编程转变。首先在看代码上要认识哪种是指令编程,哪种是函数式编程。实现这种思想上的转变,不仅仅会使你成为一个更好的Scala程序员,同时也会扩展你的视野,使你成为一个更好的程序员。

一个简单的原则,如果代码中含有var类型的变量,这段代码就是传统的指令式编程,如果代码只有val变量,这段代码就很有可能是函数式代码,因此学会函数式编程关键是不使用vars来编写代码。

来看一个简单的例子:

1defprintArgs ( args:Array[String]):Unit={

2vari=0

3while(i < args.length) {

4println (args(i))

5i+=1

6}

7}

来自Java背景的程序员开始写Scala代码很有可能写成上面的实现。我们试着去除vars变量,可以写成跟符合函数式编程的代码:

1defprintArgs ( args:Array[String]):Unit={

2for( arg <- args)

3println(arg)

4}

或者更简化为:

1defprintArgs ( args:Array[String]):Unit={

2args.foreach(println)

3}

这个例子也说明了尽量少用vars的好处,代码更简洁和明了,从而也可以减少错误的发生。因此Scala编程的一个基本原则上,能不用Vars,尽量不用vars,能不用mutable变量,尽量不用mutable变量,能避免函数的副作用,尽量不产生副作用。

第十二步: 读取文件

使用脚本实现某个任务,通常需要读取文件,本节介绍Scala读写文件的基本方法。比如下面的例子读取文件的每行,把该行字符长度添加到行首:

1importscala.io.Source

2if(args.length >0){

3for( line <- Source.fromFile(args(0)).getLines())

4println(line.length +" "+ line)

5}

6else

7Console.err.println("Please enter filename")

可以看到Scala引入包的方式和Java类似,也是通过import语句。文件相关的类定义在scala.io包中。 如果需要引入多个类,Scala使用 “_” 而非 “*”.

通过前面两篇文章的介绍,你应该对Scala编程有了一个大概的了解,可以编写一些简单的Scala脚本语言。Scala的功能远远不止这些,在后面的文章我们在一一详细介绍。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,099评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,293评论 18 399
  • 这篇讲义只讲scala的简单使用,目的是使各位新来的同事能够首先看懂程序,因为 scala 有的语法对于之前使用习...
    MrRobot阅读 2,863评论 0 10
  • 刚才和姐姐聊了会天,发现开导别人的同时,其实也是在开导自己。。。 我一直在劝姐姐,别跟自己较劲,要懂得珍惜眼前人,...
    暗黑系少女阅读 168评论 0 0
  • 午后,阳光暖暖的,北方的四月是一年之中最好的季节。到处可以看见盛开的花朵,红的,粉的,黄的...,它们开在城市...
    张明轩阅读 167评论 0 0