概述
在这篇文章中,我们将展示Scala的一个功能特性,即模式匹配。
如果你过去使用过Java或.NET,那么乍一看,它可能与switch语句相似。但是,Scala的模式匹配要强大得多!
模式匹配的不同方式
1.模式匹配:一个非常基本的例子
假设你想测试一个叫做donutType的变量。如果它的值是Glazed Donut,你会打印Very Tasty。另一方面,如果它的值是Plain Donut,那么你将打印Tasty。
val donutType = "Glazed Donut"
donutType match {
case "Glazed Donut" => println("Very tasty")
case "Plain Donut" => println("Tasty")
}
当你在IntelliJ中运行你的Scala应用程序时,你应该看到以下输出。
Very tasty
注意
- 你应该注意到,与Java或**.NET不同的是,这里没有break**语句!
- 我敢肯定,你一定看到过你的那份bug,这些bug来自于有人忘了使用break语句的事实。在Java或**.NET中,这将允许逻辑下降**到下一个case语句。
- 这也要感谢Scala,因为它的编译器足够聪明,可以防止落空,因此没有必要使用break子。
2.模式匹配并返回结果
如果你不想简单地打印出甜甜圈的不同口味等级,而是想把它存储在一个变量中,那该怎么办?
val tasteLevel = donutType match {
case "Glazed Donut" => "Very tasty"
case "Plain Donut" => "Tasty"
}
println(s"Taste level of $donutType = $tasteLevel")
当你在IntelliJ中运行你的Scala应用程序时,你应该看到以下输出。
Taste level of Glazed Donut = Very tasty
注意
- 注意,你不必像在Java或**.NET中那样使用返回**关键字。
- 相反,最后一个表达式将是返回给调用者的那个。在我们学习函数的教程时,我们会看到更多的返回类型。
3.使用通配符进行模式匹配
正如你在第1步中所学到的,没有必要使用任何断句,因为在使用模式匹配时没有落空。但是,如果你需要提供一个默认的情况呢?
println("\nStep 3: Pattern matching using the wildcard operator")
val tasteLevel2 = donutType match {
case "Glazed Donut" => "Very tasty"
case "Plain Donut" => "Tasty"
case _ => "Tasty"
}
println(s"Taste level of $donutType = $tasteLevel2")
当你在IntelliJ中运行你的Scala应用程序时,你应该看到以下输出。
Step 3: Pattern matching using the wildcard operator
Taste level of Glazed Donut = Very tasty
注意
- 如果你来自纯面向对象的编程背景,使用通配符运算符几乎肯定会感到不自然。
- 别担心,在接下来的教程中,我们会看到更多通配符操作符的例子!
4.在同一条件下的两个或多个项目的模式匹配
在我们的例子中,我们将釉面甜甜圈项目标记为非常美味。如果一个草莓甜甜圈也是非常美味的呢。这种行为似乎类似于一个OR表达式,你可以使用管道。
val tasteLevel3 = donutType match {
case "Glazed Donut" | "Strawberry Donut" => "Very tasty"
case "Plain Donut" => "Tasty"
case _ => "Tasty"
}
println(s"Taste level of $donutType = $tasteLevel3")
当你在IntelliJ中运行你的Scala应用程序时,你应该看到以下输出。
Taste level of Glazed Donut = Very tasty
5.模式匹配和在case子句中使用if表达式
与步骤4类似,你可以通过在case语句中添加if来模拟OR子句。
val tasteLevel4 = donutType match {
case donut if (donut.contains("Glazed") || donut.contains("Strawberry")) => "Very tasty"
case "Plain Donut" => "Tasty"
case _ => "Tasty"
}
println(s"Taste level of $donutType = $tasteLevel4")
当你在IntelliJ中运行你的Scala应用程序时,你应该看到以下输出。
Taste level of Glazed Donut = Very tasty
6.按类型进行模式匹配
到目前为止,我们一直在处理一些变量的值。如果你想对变量的类型进行模式匹配呢?
让我们明确声明一个变量的类型为Any,以保存一个甜甜圈的价格。Scala编译器会推断出priceOfDonut的类型为Double。
让我们用一些例子来证明吧!
println("\nStep 6: Pattern matching by types")
val priceOfDonut: Any = 2.50
val priceType = priceOfDonut match {
case price: Int => "Int"
case price: Double => "Double"
case price: Float => "Float"
case price: String => "String"
case price: Boolean => "Boolean"
case price: Char => "Char"
case price: Long => "Long"
}
println(s"Donut price type = $priceType")
当你在IntelliJ中运行你的Scala应用程序时,你应该看到以下输出。
Step 6: Pattern matching by types
Donut price type = Double
注意
- 如果你来自Java或NET,你可以认为Any类型类似于Object类。
- 换句话说,Any 是Scala类型层次结构的根。
总结
在这篇文章中,我们讨论了基本的模式匹配、将结果返回给调用者、通配符操作、同一条件下的两个或多个项目、使用if表达式以及使用类型。