实验楼学习Scala语言的笔记,课程网址为https://www.shiyanlou.com/courses/490
一、Scala简介
Scala 是一门多范式的编程语言,类似于 Java 。设计初衷是实现可伸缩的语言、并集成面向对象编程和函数式编程的各种特性。
在线 Scala 编译器Scalakata.com。
Scala环境安装(略)。
假设有一个Scala程序的文件HelloWorld.scala
编译 scalac HelloWorld.scala
运行 scala HelloWorld
注:编译之后的文件后缀为.class
HelloWorld.scala文件内容如下:
object HelloWorld{ def main(args:Array[String]){ println("Hello,World") } }
二、步入Scala前的准备
1. Scala交互式解释器
:help - 查看帮助
:quit - 退出Scala交互式解释器
在Scala解释器中输入 1+2
则解释器会输出 res0: Int = 3
- res0 是Scala解释器自动生成的变量名
- : 冒号
- Int 数据类型
- = 等于号
- 3 计算结果
2. 定义变量
Scala定义了两种类型的变量 var 和 val;
val : 类似与Java中的final,初始化之后不能再重新赋值,称之为常变量;
var : 初始化之后可以重新赋值。
例如: val msg:String = "Hello,World"
变量类型 变量名[:数据类型] = 变量值
变量类型 可以不指定,Scala会根据赋值内容推算出变量的类型。
Scala也不需要分号(;)结尾
3. 定义函数
Scala 既是面向对象的编程语言,也是面向函数的编程语言。因此函数在 Scala 语言中的地位和类是同等第一位的。
函数的定义以def开头,格式如下 def 函数名(参数名:类型[,......])[ : 返回类型] = { 代码 }
例如: def max(x:Int, y:Int):Int = {
if(x>y) x
else y
}
Scala表达式都是返回结果,函数的最后一个表达式的值就可以作为函数的结果返回,Scala避免使用return。可以没有返回类型,即Unit,相当于Java的void。
同样由于 Scala 的“ type inference ”特点,本例其实无需指定返回值的类型。对于大多数函数 Scala 都可以推测出函数返回值的类型,但目前来说回溯函数(函数调用自身)还是需要指明返回结果类型的。
4. 编写Scala脚本
Scala 本身是设计用来编写大型应用的,但它也可以作为脚本语言来执行,脚本为一系列 Scala 表达式构成以完成某个任务,比如前面的 Hello World 脚本,你也可以使用脚本来实现一些比如复制文件,创建目录之类的任务。
5. while配合使用if实现循环
var i=0 while (i < args.length) { println (args(i)) i+=1 }
Scala不支持 ++i 和 i++ 运算符;Scala访问数组的语法是使用()而非[];以上实现循环的方式并不是最好的Scala风格。
6. 使用foreach和for来
第5点使用while实现不符合Scala的风格,应该采用“函数式”风格来编写代码。
例如: args.foreach(arg => println(arg))
调用args的foreach方法,传入一个参数
若一个函数只有一个参数并且只包含一个表达式,则无需明确指明参数。上述代码还可以精简如下: args.foreach(println)
Scala还提供了功能强大的for表达式,比Java中的for功能强大的多了。后面再述。
先看看for吧。 for(arg <- args) println(arg)
7. 使用类型参数化数组
var greetStrs = new Array[String](3)
greetStrs(0)="Hello"
greetStrs(1)=","
greetStrs(2)="World "
for(i <- 0 to 2)
print(greetStrs(i))
0 to 2 相当于 (0).to(2)
Scala中所有的基本数据类型也是对象。
Scala对方法的名称没有太多的限制,开发人员可以使用符号作为方法的名称。
使用()相当于调用该对象的apply方法。
greetStrs(0) 相当于 greetStrs.apply(0)
greetStrs(0) = "Hello" 相当于 greetStrs.update(0,"Hello")
另一种定义数组的方法: var greetStrs = Array("Hello",",","World ")
8. 使用List
Scala兼有面向对象编程语言的特点,即调用某个方法不应该有任何副作用,参数一定,调用该方法返回一定的结果,而不会去修改程序的其他状态(副作用)。
数组的元素是可以被修改的,如果需要使用不可修改的序列,Scala提供了List类。
val oneTwo = List(1,2)
val threeFour = List(3,4)
val ontTwoThreeFour = oneTwo ::: threeFour
::: 操作符(其实为::: 方法)将两个列表连接起来,实际是新创建一个oneTwoThreeFour对象
List也提供了一个 :: 方法用来向List中添加一个元素。
:: 方法(操作符)是右操作符,也就是使用 :: 右边的对象来调用它的 :: 方法。
Scala中规定所有以 : 开头的操作符都是右操作符
List类还定义了 head、last、length、reverse、tail等其他方法
9. 元组(Tuples)
元组可以包含不同数据类型的数据。在方法需要返回多个结果时非常的有用。
可以使用 ._ 和 索引 来访问元组的元素,索引从1开始
Scala支持的元组的最大长度为22。目前是这样的。
Scala中的元组用 () 定义
var pair = (99, "test")
println(pair._1)
println(pair._2)
10. Sets和Maps
Scala 语言的一个设计目标是让程序员可以同时利用面向对象和面向函数的方法编写代码,因此它提供的集合类分成了可以修改的集合类和不可以修改的集合类两大类型。
比如 Array总是可以修改内容的,而 List 总是不可以修改内容的。类似的情况,Scala 也提供了两种 Sets 和 Map 集合类。
Set集合
可修改时使用全包名: var jetSet = Scala.collection.mutable.Set("Bating", "shanghai")
直接使用类名定义时可以修改: var jetSet = Set("Bating", "shanghai")
Map集合
可修改时使用全包名: var jetMap = Scala.collection.mutable.Map("Bating", "shanghai")
直接使用类名定义时可以修改: var jetMap = Set("Bating", "shanghai")
11. 函数式编程风格
简单的说函数式编程就是尽量不使用 var
Java和C#为指令式编程思想
Scala编程原则: 能不用 vars,尽量不用 vars,能不用 mutable 变量,尽量不用 mutable 变量,能避免函数的副作用,尽量不产生副作用
12. 读取文件
代码
import scala.io.source
var args = Source.fromFile("/home/aston/test.txt")
for(line <- args.getLines)
println(line.length + " " + line)
以上代码是一行一行读取文件内容。注意先在相应的目录下创建文件test.txt并输入内容
三、 类和对象入门
Scala 类定义和 Java 非常类似,也是以 class 开始,和 Java 不同的,Scala 的缺省修饰符为public,也就是如果不带有访问范围的修饰符 public 、protected、private 等,Scala 将默认定义为 public 。
类的方法以 def 定义开始,要注意的Scala的方法的参数都是 val类型,而不是 var 类型,因此在函数体内不可以修改参数的值
类的方法分两种,一种是有返回值的,一种是不含返回值的,没有返回值的主要是利用代码的“副作用”,比如修改类的成员变量的值或者读写文件等。Scala 内部其实将这种函数的返回值定为 Unit(类同 Java 的 void 类型),对于这种类型的方法,可以省略掉 = 号
Scala 比 Java 更加面向对象,这是因为 Scala 不允许类保护静态元素(静态变量或静态方法)。在 Scala 中提供类似功能的是成为“ Singleton(单例对象)”的对象。
伴侣对象( companion )
单例对象( singleton )
Traint,相当于Java的interface,不过可以有方法的实现
四、 基本数据类型及其操作
Scala的数据类型都是对象
Scala支持隐式自动转换 ,因为如此,所以Scala可以对数据类型扩展
数据类型
整数类型: Byte、Short、Int、Long和Char
浮点型: Float、Double
字符型: String
布尔型: Boolean
Scala中字面量也支持方法
算术运算符: + - * /
关系和逻辑运算符: < > <= >= ! && || 等
逻辑运算符支持 短路 运算
位操作符: & | ^ ~
对象恒等比较: == 和 !=
1. 运算符的优先级和左右集合
Scala 的操作符的优先级和 Java 基本相同,可以使用 () 改变操作符的优先级。
操作符一般为左结合,Scala 规定了操作符的结合性由操作符的最后一个字符定义。对于以 : 结尾的操作符都是右结合,其它的操作符多是左结合