第4章:Scala(混合范式)
一、导读
1.1 本章学习目标
第4章介绍 Scala——一门融合了面向对象和函数式编程的语言。Scala 运行在 JVM 上,与 Java 完全互操作,同时提供了更强大的类型系统和更简洁的语法。
本章的核心学习目标包括:
- 理解 Scala 的混合范式:面向对象 + 函数式
- 掌握 trait 和模式匹配
- 理解 Scala 的 Actor 并发模型
- 体验隐式转换的强大与危险
1.2 为什么本章如此重要
Scala 证明了面向对象和函数式编程不是对立的——它们可以和谐共存。Scala 的 trait 比 Java 的接口更强大,模式匹配比 switch 更灵活,隐式转换让 DSL 成为可能。理解 Scala 的设计思想,能帮你在任何语言中更好地融合多种编程范式。
1.3 核心问题引导
Scala 如何融合面向对象和函数式编程?
trait 和 Java 的接口有什么本质区别?
模式匹配为什么比 switch 强大得多?
隐式转换是利器还是陷阱?
二、核心概念详解
2.1 混合范式
scala
// 面向对象
class Person(val name: String, var age: Int) {
def greet: String = s"Hello, I'm $name, age $age"
}
// 函数式
val numbers = List(1, 2, 3, 4, 5)
val doubled = numbers.map(_ * 2)
val sum = numbers.foldLeft(0)(_ + _)
// 两者结合
class Calculator {
def compute(op: String, a: Int, b: Int): Int = op match {
case "+" => a + b
case "-" => a - b
case "*" => a * b
case "/" => a / b
}
}2.2 Trait
scala
trait Flyable {
def fly(): String
}
trait Swimmable {
def swim(): String
}
trait Singable {
def sing(): String = "La la la" // 默认实现
}
// 多重继承
class Duck extends Flyable with Swimmable with Singable {
def fly(): String = "Flying high!"
def swim(): String = "Swimming gracefully"
}
val duck = new Duck
println(duck.fly()) // Flying high!
println(duck.sing()) // La la la2.3 模式匹配
scala
// 强大的模式匹配
def describe(x: Any): String = x match {
case i: Int if i > 0 => s"Positive integer: $i"
case s: String => s"String of length ${s.length}"
case List(1, _*) => "List starting with 1"
case (a, b) => s"Tuple: ($a, $b)"
case null => "null"
case _ => "Unknown"
}
// 代数数据类型
sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(width: Double, height: Double) extends Shape
def area(shape: Shape): Double = shape match {
case Circle(r) => Math.PI * r * r
case Rectangle(w, h) => w * h
}2.4 Actor 模型
scala
import akka.actor._
// 定义消息
case class Greet(who: String)
case class Greeted(greeting: String, who: String)
// 定义 Actor
class Greeter extends Actor {
def receive = {
case Greet(who) =>
println(s"Hello, $who!")
sender() ! Greeted(s"Hello, $who!", who)
}
}
// 使用
val system = ActorSystem("HelloSystem")
val greeter = system.actorOf(Props[Greeter], "greeter")
greeter ! Greet("World")三、实战案例
3.1 案例一:用模式匹配实现表达式求值
scala
sealed trait Expr
case class Num(value: Double) extends Expr
case class Add(left: Expr, right: Expr) extends Expr
case class Mul(left: Expr, right: Expr) extends Expr
case class Neg(expr: Expr) extends Expr
def eval(expr: Expr): Double = expr match {
case Num(v) => v
case Add(l, r) => eval(l) + eval(r)
case Mul(l, r) => eval(l) * eval(r)
case Neg(e) => -eval(e)
}
def show(expr: Expr): String = expr match {
case Num(v) => v.toString
case Add(l, r) => s"(${show(l)} + ${show(r)})"
case Mul(l, r) => s"(${show(l)} * ${show(r)})"
case Neg(e) => s"(-${show(e)})"
}
val expr = Add(Mul(Num(3), Num(4)), Num(2))
println(show(expr)) // ((3.0 * 4.0) + 2.0)
println(eval(expr)) // 14.0四、本章小结
混合范式:Scala 无缝融合面向对象和函数式编程。
Trait:比 Java 接口更强大,支持多重继承和默认实现。
模式匹配:比 switch 强大,支持类型、守卫、解构。
Actor 模型:消息传递的并发模型,避免共享状态。
五、思考与练习
Scala 的 trait 解决了 Java 接口的什么局限?
模式匹配和 Visitor 模式有什么相似之处?
Actor 模型和线程+锁模型相比有什么优势?