Scala 简介
Scala 属于“可伸展语言”,源于它可以随使用者的需求而改变和成长。Scala 可以应用在很大范围的编程任务上,小到脚本大到建立系统均可以。 Scala 跑在标准 Java 平台上,可以与所有 Java 库实现无缝交互。它把面向对象和函数式编程理念加入到静态类型语言中。Scala可以培育新的类型和新的控制结构,使它用起来更像是内建的类型和控制结构一样,它没有提供所有你在一种“完美齐全”语言中可能需要的东西,而是把制作这些东西的工具放在了你的手中。
Scala 编程总览
Scala 解释器
Scala 解释器是一个编写 Scala 表达式和程序的交互式 “ shell ”,在解释器里输入一个表达式,它将计算这个表达式并打印结果。在终端输入 scala 即可打开解释器:
? ~ scala Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_65). Type in expressions to have them evaluated. Type :help for more information.
在输入表达式并回车之后:
scala> 1 + 2 res0: Int = 3
解释器计算表达式后打印的结果包括:
·一个自动产生的或用户定义的名称说明计算的值(res0,表示结果0)
·一个冒号(:),跟着表达式的类型(Int),
·一个等号(=),
·计算表达式所得到的结果(3)。
resX识别符还将用在后续的代码行中。例如,既然res0已在之前设为3,res0 * 3就是9:
scala> res0 * 3 res1: Int = 9
变量
Scala有两种变量,val和var。val一旦初始化了再赋值了, var则可以在它生命周期中被多次赋值。下面是一个val的定义:
scala> val msg = "hello world" msg: String = hello world
这个语句引入了msg当作字串"hello world"的名字。类型是 String ,因为Scala的字串是由Java的String类实现的。Scala能自动理解省略的类型。在这个例子里,用一个字串文本初始化了msg,Scala推断msg的类型是 String 。不过,也可以显式地定义类型,显式的类型标注不但可以确保 Scala 编译器推断你倾向的类型,还可以作为将来代码读者有用的文档。 Scala 里变量的类型在其名称之后,用冒号分隔。如:
scala> val msg2:String = "hello world" msg2: String = hello world
由于msg是val不是var,不能再给它赋值,否则会报错:
scala> msg = "hello" <console>:11: error: reassignment to val msg = "hello" ^
如果需要可重赋值,应该使用var定义变量:
scala> var msg3 = "hello world" msg3: String = hello world scala> msg3 = "hello" msg3: String = hello
要输入一些能跨越多行的东西,只要一行行输进去就行。如果输到行尾还没结束,解释器将在下一行回应一个竖线:
scala> var multLine = | "next line" multLine: String = next line
如果输入了一些错误的东西,而解释器仍在等着更多的输入,可以通过按两次回车取消掉:
scala> val oops = | | You typed two blank lines. Starting a new command.
函数
Scala 里函数定义写法:
scala> def max(x: Int, y: Int): Int = { | if (x > y) x | else y | } max: (x: Int, y: Int)Int
函数的基本结构如图所示:
有时候Scala编译器会需要定义函数的结果类型。比方说,如果函数是递归的就必须显式地定义函数结果类型。然而在max的例子里,你可以不用写结果类型,编译器也能够推断它。如果函数仅由一个句子组成,可以可选地不写大括号:
scala> def max2(x: Int, y: Int) = if (x > y) x else y max2: (x: Int, y: Int)Int
一旦定义了函数,就可以用它的名字调用它,如:
scala> max(1,2) res3: Int = 2
还有既不带参数也不返回有用结果的函数定义:
scala> def hello() = println("hello world") hello: ()Unit
当定义hello()函数,解释器会回应一个 hello: ()Unit 。“hello”是函数名。空白的括号说明函数不带参数。 Unit 是 hello 的结果类型。 Unit 的结果类型指的是函数没有返回有用的值。因此结果类型为 Unit 的方法,仅仅是为了它们的副作用而运行。在 hello() 的例子里,副作用是在标准输出上打印一句客气的助词。
脚本
运行脚本的方法为 scala [file.scala],通过 Scala 的名为 args 的数组可以获得传递给 Scala 脚本的命令行参数。 Scala 里数组从 0 开始,通过括号里指定索引访问一个元素。
while 循环;if 判断;foreach 和 for枚举
用如下方式写 while 和 if :
var i = 0 while (i < args.length) { if (i != 0) print (" ") print (args(i)) i += 1 }
像这样一次性发出一个指令式的命令,用循环去枚举,并经常改变共享在不同函数之间的状态称为指令式风格编程, Scala 允许指令式地编程,但函数式风格编程更舒适:
args.foreach(arg => println(arg))
这行代码中,在 args 上调用 foreach 方法,并把它传入函数,传入了带有一个叫做 arg 参数的函数文本,函数体是 println(arg) 。
Scala 解释器推断 arg 的类型是 String ,因为 String 是调用 foreach 的那个数组的元素类型。显式的需要加上类型名,要把参数部分包裹在括号里:
args.foreach((arg: String) => println(arg))
如果函数文本由带一个参数的一句话组成,甚至都不需要显式命名和指定参数:
args.foreach(println)
总而言之,函数文本的语法就是,括号里的命名参数列表,右箭头,然后是函数体:
Scala 里指令式 for 使用方法:
for (arg <- args) println(arg)
这个表达式里“for”之后的括号包含 arg<-args 。<- 右侧的是熟悉的 args 数组。<-左侧的是“arg”, val 的名称(不是 var )。尽管 arg 可能感觉像 var ,因为他在每次枚举都会得到新的值,但它的确是 val : arg 不能在 for 表达式的函数体中重新赋值。取而代之,对每个 args 数组的元素,一个新的 arg val 将被创建并初始化为元素值,然后 for 的函数体将被执行。