Scala 语法基础
Scala语法较复杂,参考软件的增量开发,学习一门编程语言也应先找到一种能够驾驭的表达方式,之后再逐步添枝加叶。Scala同时支持面向对象和函数式编程,是其语法复杂的原因之一。一些教程非常全面,但也因为全面,导致难以抽丝剥茧,抓住主干。
以下内容关注最简单的基础语法,希望根据这些内容,可以尝试编写面向对象风格的Scala代码。
语句
Scala允许语句结尾不加;,这一点类似JavaScript。
变量定义
val定义不可变变量(常量),var定义可变变量:
val msg1 = "Hello World"var msg2 = "Hello Wrold"val msg3: String = "Hello World"定义变量时,类型声明在变量右侧,而且是可选的,可以不声明,编译器会自动推断。Scala中的基本类型包括:
Byte、Short、Int、Long、Char、String、Float、Double、Boolean
函数定义
函数即方法,下面是定义函数的例子:
def max(x: Int, y: Int): Int = { if (x > y) { return x } else { return y }}与Java中方法定义的显著区别有三处:一是使用def关键字定义函数;二是类型声明在变量右侧,上文已提及;三是函数声明和函数体中间使用=连接。
注意函数声明的参数必须明确定义类型,编译器无法自动推断入参类型。返回类型则是可选的,除非函数使用了递归。另外,return关键字也是可选的,如果没有显式的返回语句,程序会将最后一次运算结果作为返回。
当然if后是单个语句也可以不使用大括号,因此该函数还可以这样描述:
def max2(x: Int, y: Int) = if (x > y) x else y选择结构
上面的示例已经用到了if语句,Scala的if语句并无特殊之处,不过与其他语言相比,Scala用模式匹配的概念代替传统的switch结构:
val a = 1a match { case 1 => println(1) case 2 => println(2) case _ =>}_通配符匹配所有值,用于捕获默认情况。匹配表达式中,备选项永远不会掉到下一个case,因此不需要break或return。(如果将_放到首句,程序不会继续向下执行)。但是要小心,如果程序没有匹配到选项,会抛出MatchError。
循环结构
while循环并不是Scala推荐的代码风格:
var i = 0while (i < 5) { println(i) i += 1}似乎并没有难以理解的地方,这就是典型的while循环。与指令式语言相比,Scala没有++运算符,只能使用i += 1这样的语句。
提起while,就一定会想到for。Scala中的for循环与指令式语言有一些差异,简单的示例如下,程序会从0打印直到5(不包括5)。
for (i <- 0 until 5) { println(i)}Scala不推荐while循环,而更倾向于函数式的编程风格,用于遍历的foreach方法就是其一:
"abc".foreach(c => println(c))程序会依次换行打印出a b c三个字符。如果函数体只有一行语句并只有一个参数,这行代码还可以更简洁:
"abc".foreach(println)数组
Scala的数组并不在语言层面实现,可以实例化Array类来使用。相应的,数组下标使用小括号(也就是方法参数)表示:
val greet = new Array[String](3)greet(0) = "a"greet(1) = "b"greet(2) = "c"greet.foreach(println)实例化对象时,也可以直接传入默认参数。Array确实只是一个普通的类,下面的书写方式并没有黑魔法,只是用到了样本类。关于样本类,后文有提及。
val greet2 = Array("a", "b", "c")greet2.foreach(println)类
类使用class关键字定义,类中也包含字段和方法,即典型的面向对象。与Python不同,Scala仍然支持权限控制:
class Accumulator { private var sum = 0 def add(b: Byte): Unit = { sum += b println(sum) }}单例对象
单例对象(Singleton对象)相当于Java中的静态类,使用object替代class关键字定义。单例对象由程序共享,可直接调用。单例对象可以作为程序入口,即将main方法定义在单例对象中。下面的程序从上面定义的Accumulator类中实例化出对象c,并调用其add方法,最终程序打印1:
object Run { def main(args: Array[String]): Unit = { val a = new Accumulator a.add(1) }}在同一源文件中,当单例对象和类同名时,称单例对象为类的伴生对象,类为单例对象的伴生类。类可以访问其伴生对象的私有属性和方法。
构造方法
Scala中构造方法的规则比Java要严格。Scala通过类参数的概念来实现构造方法:
class Accumulator(a: Int, b: Int)如果类没有主体,大括号是可以省略的。实例化这个类时,就需要传入参数。在Java中的构造方法重载,对应Scala中的辅助构造器,它看起来像这样:
class Accumulator(a: Int, b: Int) { def this(c:...剩余内容已隐藏