Scala 基础语法学习文档
一、Scala 简介
Scala 是一门多范式编程语言,集成了面向对象编程和函数式编程的各种特性。如果你之前是一名 Java 程序员,并了解 Java 语言的基础知识,那么你能很快学会 Scala 的基础语法。
Scala 与 Java 的主要区别
- Scala 语句末尾的分号
;是可选的 - Scala 支持函数式编程范式
- Scala 具有更强大的类型推断能力
- Scala 代码更加简洁
核心概念
Scala 程序可以认为是对象的集合,通过调用彼此的方法来实现消息传递。以下是核心概念:
| 概念 | 说明 |
|---|---|
| 对象 (Object) | 对象有属性和行为。例如:一只狗的属性有:颜色、名字;行为有:叫、跑、吃等。对象是一个类的实例。 |
| 类 (Class) | 类是对象的抽象,而对象是类的具体实例。 |
| 方法 (Method) | 方法描述基本的行为,一个类可以包含多个方法。 |
| 字段 (Field) | 每个对象都有它唯一的实例变量集合,即字段。对象的属性通过给字段赋值来创建。 |
二、第一个 Scala 程序
交互式编程
交互式编程不需要创建脚本文件,可以通过以下命令调用:
bash
$ scala
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_31).
Type in expressions to have them evaluated.
Type :help for more information.
scala> 1 + 1
res0: Int = 2
scala> println("Hello World!")
Hello World!
脚本形式
创建 HelloWorld.scala 文件:
scala
object HelloWorld {
def main(args: Array[String]) = {
println("Hello, world!")
}
}
编译和运行:
bash
$ scalac HelloWorld.scala
Hello, world!
Scala 3 新语法
Scala 3 引入了更简洁的程序入口语法:
scala
@main def hello() = println("Hello, Scala developer!")
三、基本语法规则
1. 大小写敏感
Scala 是大小写敏感的,标识符 Hello 和 hello 在 Scala 中会有不同的含义。
2. 类名命名规则
- 所有类名的第一个字母要大写
- 如果需要使用几个单词来构成一个类的名称,每个单词的第一个字母要大写(大驼峰命名)
scala
class MyFirstScalaClass
class Person
class OrderProcessor
3. 方法名称命名规则
- 所有方法名称的第一个字母用小写
- 如果若干单词被用于构成方法的名称,则每个单词的第一个字母应大写(小驼峰命名)
scala
def myMethodName()
def calculateTotal()
def processOrder()
4. 程序文件名
程序文件的名称应该与对象名称完全匹配(新版本不需要了,但建议保留这种习惯)。保存文件时,应该保存它使用的对象名称,并追加 .scala 为文件扩展名。
5. 程序入口
Scala 程序从 main() 方法开始处理,这是每一个 Scala 程序的强制程序入口部分。
scala
object Main {
def main(args: Array[String]): Unit =
println("Hello, Scala developer!")
}
四、标识符
Scala 可以使用两种形式的标识符:字符数字和符号。
字符数字标识符
- 使用字母或是下划线开头,后面可以接字母或是数字
- 符号
$在 Scala 中也看作为字母 - 以
$开头的标识符为保留的 Scala 编译器产生的标识符使用,应用程序应该避免使用
scala
val myValue = "hello"
var myVariable = 123
val _temp = 10
符号标识符
符号标识符包含一个或多个符号,如 +、:、? 等:
scala
+ ++ ::: < ?> :->
Scala 内部实现时会使用转义的标识符,比如 -> 使用 $colon$minus$greater 来表示。
混合标识符
混合标识符由字符数字标识符后面跟着一个或多个符号组成:
scala
unary_+ // Scala 对 + 方法的内部实现时的名称
字面量标识符
字面量标识符为使用反引号 ````` 定义的字符串:
scala
Thread.`yield`() // yield 为 Scala 中的关键字,必须使用反引号
五、命名约定
常量命名
常量使用大驼峰命名法:
scala
object Container {
val MyConstant = 10
}
值和变量命名
值和变量使用小驼峰命名法:
scala
val myValue = "hello"
var myVariable = 123
六、Scala 关键字
以下是 Scala 保留关键字,不能使用这些关键字作为变量名:
| abstract | case | catch | class |
| def | do | else | extends |
| false | final | finally | for |
| forSome | if | implicit | import |
| lazy | match | new | null |
| object | override | package | private |
| protected | return | sealed | super |
| this | throw | trait | try |
| true | type | val | var |
| while | with | yield | |
| - | : | = | => |
| <- | <: | <% | >: |
| # | @ |
七、注释
Scala 类似 Java 支持单行和多行注释。多行注释可以嵌套,但必须正确嵌套。
单行注释
scala
// 这是单行注释
多行注释
scala
/*
* 这是多行注释
* 可以跨越多行
*/
嵌套注释(Scala 特有)
scala
/*
* 外层注释开始
* /*
* 内层注释
*/
* 外层注释结束
*/
八、变量声明
Scala 有两种类型的变量:val 和 var。
val - 不可变变量
val 声明的变量是不可变的,类似于 Java 中的 final 变量,一旦初始化就不能重新赋值:
scala
val a = 0
val x: Int = 1 // 显式类型声明
val s = "Hello" // 类型推断
val nums = List(1,2,3)
val p = Person("Martin", "Odersky") // 对象实例化
var - 可变变量
var 声明的变量是可变的,可以重新赋值:
scala
var b = 1
var x = 5
var x: Double = 5 // 显式类型声明
x = 10 // 可以重新赋值
显式类型 vs 隐式类型
scala
val x: Int = 1 // 显式类型声明
val x = 1 // 隐式类型声明,编译器推断类型
最佳实践
推荐优先使用 val,只有在确实需要修改变量值时才使用 var。这有助于编写更加函数式和安全的代码。
九、数据类型
Scala 是强类型语言,但具有强大的类型推断能力。
基本数据类型
| 数据类型 | 描述 |
|---|---|
| Byte | 8位有符号整数 |
| Short | 16位有符号整数 |
| Int | 32位有符号整数 |
| Long | 64位有符号整数 |
| Float | 32位单精度浮点数 |
| Double | 64位双精度浮点数 |
| Char | 16位无符号 Unicode 字符 |
| Boolean | true 或 false |
| String | 字符串 |
| Unit | 表示无值,类似 void |
| Null | 空引用 |
| Nothing | 所有类型的子类型 |
| Any | 所有类型的超类 |
类型声明示例
scala
val numInt: Int = 10
val numLong: Long = 100000L
val numFloat: Float = 10.5f
val numDouble: Double = 10.5
val bool: Boolean = true
val char: Char = 'A'
val str: String = "Hello Scala"
十、方法定义
基本语法
scala
def methodName(param1: Type1, param2: Type2): ReturnType =
// 方法体
方法定义示例
scala
def sum(a: Int, b: Int): Int = a + b
def concatenate(s1: String, s2: String): String = s1 + s2
// 省略返回类型(编译器自动推断)
def sum(a: Int, b: Int) = a + b
def concatenate(s1: String, s2: String) = s1 + s2
方法调用
scala
val x = sum(1, 2)
val y = concatenate("foo", "bar")
十一、类和对象
类定义
scala
class Person(name: String, age: Int) {
def greet(): Unit = {
println(s"Hello, my name is $name")
}
}
对象(单例对象)
scala
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello, World!")
}
}
对象实例化
scala
val p = Person("Al", "Pacino")
val nums = List(1, 2, 3)
十二、函数式编程特性
for 推导式
Scala 2 语法:
scala
val y = for (i <- nums) yield i * 2
Scala 3 语法:
scala
val y = for i <- nums yield i * 2
集合操作
scala
val nums = List(1, 2, 3, 4, 5)
val sum = nums.reduceLeft(_ + _)
val z = nums
.filter(_ > 100)
.filter(_ < 10_000)
.map(_ * 2)
十三、Scala 2 vs Scala 3 主要差异
| 特性 | Scala 2 | Scala 3 |
|---|---|---|
| 程序入口 | def main(args: Array[String]) |
@main def hello() |
| for 推导式 | for (i <- nums) yield i * 2 |
for i <- nums yield i * 2 |
| 数字分隔符 | 不支持 | 10_000 |
| 语法简洁性 | 相对繁琐 | 更加简洁 |
十四、代码示例汇总
完整示例
scala
object Main {
def main(args: Array[String]): Unit = {
println("=== Scala 基础语法示例 ===")
val immutableValue = 10
var mutableValue = 20
println(s"不可变值: $immutableValue")
println(s"可变值: $mutableValue")
mutableValue = 30
println(s"修改后的可变值: $mutableValue")
val result = sum(5, 3)
println(s"sum(5, 3) = $result")
val greeting = concatenate("Hello, ", "Scala!")
println(s"拼接结果: $greeting")
val nums = List(1, 2, 3, 4, 5)
val doubled = nums.map(_ * 2)
println(s"列表翻倍: $doubled")
}
def sum(a: Int, b: Int): Int = a + b
def concatenate(s1: String, s2: String): String = s1 + s2
}
十五、建议
- 优先使用
val:尽量使用不可变变量,这有助于编写更加安全和易于推理的代码 - 遵循命名规范:保持代码风格一致,提高可读性
- 利用类型推断:在类型明显的情况下,可以省略类型声明,让代码更简洁
- 学习函数式编程:Scala 的强大之处在于函数式编程特性,建议深入学习