学习《Scala编程》(第三版)的学习笔记。
一门可伸缩的语言
Scala,源于"scalable language",可伸缩的语言。从技术上来看,Scala是一门综合了面向对象和函数式编程概念的静态类型的编程语言。很适合编写将Java组件组装在一起的脚本。
在Scala中,面向对象的实现是纯的:每个值都是对象,每个操作都是方法调用。Scala也是功能完整的函数式编程语言。以两大核心理念为指导。第一个理念是函数式一等的值。可以将函数作为参数传递给其他函数,作为返回值返回它们。第二个核心理念是程序中的操作应该将输入值映射成输出值,而不是当场修改数据。即,方法只能通过接收入参和返回结果这两种方式与外部环境通信。
最重要的四点
兼容性
Scala程序会被编译成JVM字节码,运行期性能跟Java程序相当。Scala代码可以调用Java方法、访问Java字段、从Java类继承、实现Java接口。几乎所有的Scala代码都重复使用Java类库。
精简性
跟Java相比,代码行数可能相差十倍之多。Scala的语法避免了Java程序中常见的一些样板的代码。可以写分号,也可以不写分号。
// 类和构造方法比较
//Java
class Myclass {
private int index;
private String name;
public Myclass(int index, String name) {
this.index = index;
this.name = name;
}
}
//Scala
class Myclass(index Int, name String)
Scala编译器会产出带有两个私有实例变量(一个为index的Int和一个名为name的String)和一个接收这两个变量初始值的参数的构造方法的类。这个构造方法会用传入的参数值来初始化它的两个实例变量。
高级性
提升接口设计的抽象级别。
boolean nameHasUpperCase = false;
for (int i = 0; i < name; i++) {
if (Character.isUpperCase(name.charAt(i))) {
nameHasUpperCase = true;
break;
}
}
//Scala
val nameHasUpperCase = name.exists(_.isUpper)
Java将字符串当做低级别的实体,在循环中逐个字符地遍历。而Scala代码将同样的字符串当做更高级别的字符序列sequence,用predicate来查询。不理解这个地方。但第一感觉是,将接口抽象到更高,使得用户通过简易的API就可以实现查看字符串是否有大写这个功能。
静态类型
Scala不仅拥有跟Java类似的允许嵌套类的类型系统,还允许使用泛型来对类型进行参数化,用交集来组合类型,以及用抽象类型来隐藏类型的细节。
Scala入门
Scala在变量名之后,变量名和类型之间用:隔开
val msg : java.lang.String = "Hello world!"
val msg : String = Hello,world
val 和 var
要重新复制就用var定义,val定义后不可重新赋值。
定义函数
def max(x:Int, y:Int) : Int = {
if(x > y) x
else y
}
每个参数的后面都必须加上以冒号:开始的类型标注,因为Scala编译器并不会推断函数参数的类型。以及要定义函数的结果类型。
Scala的Unit类型和Java的void类型类似。
Scala脚本
将代码放入.scala文件,然后执行
scala hello.scala
注释
和Java一样,//和/* */
while循环
var i = 0
while(i < args.length) {
printlin(args(i))
i += 1
}
用foreach和for遍历
使用函数式的风格循环。
args.foreach(arg => println(arg))
args.foreach(println)
用类型参数化数组
new来实例化对象或类的实例。参数化就是创建实例时对实例做配置,用值参数化一个实例。
val big = new java.math.BigInteger("12345")
val greetStrings = new Array[String](3)
for(i <- 0 to 2)
print(greetStrings(i))
Scala将一切都当做带有方法的对象来处理。
val numNames = Array("zero", "one", "two")
val numNames2 = Array.apply("zero", "one", "two")
List
Scala的List是不可变的,Java的List是可变的。
List有个方法“:::”,用于列表拼接。
val twoThree = List(2, 3)
val oneTwoThree = 1 :: twoThree
println(oneTwoThree)
使用集和映射
Set有可变和不可变两种方式。如果想要一个可变集,需要import scala.collection.mutable。就有+=方法。HashSet分别继承Set,也有可变和不可变两种。
Scala另一个集合类是Map,也有可变和不可变版本。同时HashMap分别继承。
函数式编程风格
一个向函数式风格转变的方向是尽可能不用var。
从文件读取文本行
import scala.io.Source
if (args.length > 0) {
for (line <- Source.fromFile(args(0)).getLines())
println(line.length + " " + line)
}
else
Console.err.println("please enter filename")