一、模式匹配

Scala支持模式匹配机制,可以代替swith语句、执行类型检查、以及支持析构表达式等。

1.1 更好的swith

Scala不支持swith,可以使用模式匹配match...case语法代替。但是match语句与Java中的switch有以下三点不同:

  • Scala中的case语句支持任何类型;而Java中case语句仅支持整型、枚举和字符串常量;
  • Scala中每个分支语句后面不需要写break,因为在case语句中break是隐含的,默认就有;
  • 在Scala中match语句是有返回值的,而Java中switch语句是没有返回值的。如下:
object ScalaApp extends App {

  def matchTest(x: Int) = x match {
    case 1 => "one"
    case 2 => "two"
    case _ if x > 9 && x < 100 => "两位数"   //支持条件表达式 这被称为模式守卫
    case _ => "other"
  }

  println(matchTest(1))   //输出 one
  println(matchTest(10))  //输出 两位数
  println(matchTest(200)) //输出 other
}

1.2 用作类型检查

object ScalaApp extends App {

  def matchTest[T](x: T) = x match {
    case x: Int => "数值型"
    case x: String => "字符型"
    case x: Float => "浮点型"
    case _ => "other"
  }

  println(matchTest(1))     //输出 数值型
  println(matchTest(10.3f)) //输出 浮点型
  println(matchTest("str")) //输出 字符型
  println(matchTest(2.1))   //输出 other
}

1.3 匹配数据结构

匹配元组示例:

object ScalaApp extends App {

  def matchTest(x: Any) = x match {
    case (0, _, _) => "匹配第一个元素为0的元组"
    case (a, b, c) => println(a + "~" + b + "~" + c)
    case _ => "other"
  }

  println(matchTest((0, 1, 2)))             // 输出: 匹配第一个元素为0的元组
  matchTest((1, 2, 3))                      // 输出: 1~2~3
  println(matchTest(Array(10, 11, 12, 14))) // 输出: other
}

匹配数组示例:

object ScalaApp extends App {

  def matchTest[T](x: Array[T]) = x match {
    case Array(0) => "匹配只有一个元素0的数组"
    case Array(a, b) => println(a + "~" + b)
    case Array(10, _*) => "第一个元素为10的数组"
    case _ => "other"
  }

  println(matchTest(Array(0)))          // 输出: 匹配只有一个元素0的数组
  matchTest(Array(1, 2))                // 输出: 1~2
  println(matchTest(Array(10, 11, 12))) // 输出: 第一个元素为10的数组
  println(matchTest(Array(3, 2, 1)))    // 输出: other
}

1.4 提取器

数组、列表和元组能使用模式匹配,都是依靠提取器(extractor)机制,它们伴生对象中定义了unapplyunapplySeq方法:

  • unapply:用于提取固定数量的对象;
  • unapplySeq:用于提取一个序列;

这里以数组为例,Array.scala定义了unapplySeq方法:

def unapplySeq[T](x : scala.Array[T]) : scala.Option[scala.IndexedSeq[T]] = { /* compiled code */ }

unapplySeq返回一个序列,包含数组中的所有值,这样在模式匹配时,才能知道对应位置上的值。

二、样例类

2.1 样例类

样例类是一种的特殊的类,它们被经过优化以用于模式匹配,样例类的声明比较简单,只需要在class前面加上关键字case。下面给出一个样例类及其用于模式匹配的示例:

//声明一个抽象类
abstract class Person{}
// 样例类Employee
case class Employee(name: String, age: Int, salary: Double) extends Person {}
// 样例类Student
case class Student(name: String, age: Int) extends Person {}

当你声明样例类后,编译器自动进行以下配置:

  • 构造器中每个参数都默认为val
  • 自动地生成equals, hashCode, toString, copy等方法;
  • 伴生对象中自动生成apply方法,使得可以不用new关键字就能构造出相应的对象;
  • 伴生对象中自动生成unapply方法,以支持模式匹配。

除了上面的特征外,样例类和其他类相同,可以任意添加方法和字段,扩展它们。

2.3 用于模式匹配

样例的伴生对象中自动生成unapply方法,所以样例类可以支持模式匹配,使用如下:

object ScalaApp extends App {

  def matchTest(person: Person) = person match {
    case Student(name, _) => "student:" + name
    case Employee(_, _, salary) => "employee salary:" + salary
    case _ => "other"
  }

  println(matchTest(Student("heibai", 12)))        //输出: student:heibai
  println(matchTest(Employee("ying", 22, 999999))) //输出: employee salary:999999.0
}

参考资料

  1. Martin Odersky . Scala编程(第3版)[M] . 电子工业出版社 . 2018-1-1
  2. 凯.S.霍斯特曼 . 快学Scala(第2版)[M] . 电子工业出版社 . 2017-7

更多大数据系列文章可以参见个人 GitHub 开源项目: 程序员大数据入门指南

Scala 学习之路(十一)—— 模式匹配的更多相关文章

  1. scala学习之路一

    所谓学习,那么首先就先简单介绍一下scala吧 1.scala的介绍 Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性. Scal ...

  2. Scala学习之路 (十)Scala的Actor

    一.Scala中的并发编程 1.Java中的并发编程 ①Java中的并发编程基本上满足了事件之间相互独立,但是事件能够同时发生的场景的需要. ②Java中的并发编程是基于共享数据和加锁的一种机制,即会 ...

  3. Scala学习之路 (六)Scala的类、对象、继承、特质

    一.类 1.类的定义 scala语言中没有static成员存在,但是scala允许以某种方式去使用static成员这个就是伴生机制,所谓伴生,就是在语言层面上,把static成员和非static成员用 ...

  4. Scala学习之路----基础入门

    一.Scala解释器的使用 REPL:Read(取值)-> Evaluation(求值)-> Print(打印)-> Loop(循环) scala解释器也被称为REPL,会快速编译s ...

  5. Scala 学习之路(七)—— 常用集合类型之 Map & Tuple

    一.映射(Map) 1.1 构造Map // 初始化一个空map val scores01 = new HashMap[String, Int] // 从指定的值初始化Map(方式一) val sco ...

  6. Scala 学习之路(六)—— 常用集合类型之 List & Set

    一.List字面量 List是Scala中非常重要的一个数据结构,其与Array(数组)非常类似,但是List是不可变的,和Java中的List一样,其底层实现是链表. scala> val l ...

  7. zigbee学习之路(十一):看门狗

    一.前言 今天,我们要通过实验学习和认识一下看门狗的使用,看门狗是为了防止防止程序跑飞的,通过不断的喂狗,使看门狗能持续监管程序的运行状态,当程序跑飞时,能及时把程序拽回来. 二.原理与分析 在CPU ...

  8. Scala学习之路 (九)Scala的上界和下届

    一.泛型 1.泛型的介绍 泛型用于指定方法或类可以接受任意类型参数,参数在实际使用时才被确定,泛型可以有效地增强程序的适用性,使用泛型可以使得类或方法具有更强的通用性.泛型的典型应用场景是集合及集合中 ...

  9. Scala学习之路 (八)Scala的隐式转换和隐式参数

    一.概念 Scala 2.10引入了一种叫做隐式类的新特性.隐式类指的是用implicit关键字修饰的类.在对应的作用域内,带有这个关键字的类的主构造函数可用于隐式转换. 隐式转换和隐式参数是Scal ...

随机推荐

  1. VSCode 小鸡汤 第00期 —— 安装和入门

    简介 这将是一个新的系列,将会以 Visual Studio Code(后文都简称为 VSCode 啦)的操作,环境配置,插件介绍为主,为大家不定期的介绍 VSCode 的一些操作技巧,所以取名 VS ...

  2. 【转】mybatis 一对一与一对多collection和association的使用

    转自:https://www.cnblogs.com/yansum/p/5819973.html (有修改和补充,红色字体部分)   在mybatis如何进行一对一.一对多的多表查询呢?这里用一个简单 ...

  3. Matlab Tricks(十七)—— 使用 Latex

    >> set(text, 'Interpreter') 'none' 'tex' 'latex' % Matlab将返回'Interpreter'(解释器,对 text 文本的解释)所包含 ...

  4. Distinct去除重复项

    之前在做权限模块时,因不同角色可能拥有相同的菜单,导致呈现在浏览器上时出现重复菜单项,所以需要在获取用户拥有菜单项时需要过滤重复项, 用到了Distinct,两个重载 public static IQ ...

  5. 3ds Max建模,Blend设计,VS2008控制WPF的3D模型例子

    原文:3ds Max建模,Blend设计,VS2008控制WPF的3D模型例子 3ds Max建模,Blend设计,VS2008控制WPF的3D模型例子   所用的软件 3ds Max 9.0,Mic ...

  6. 怎么给罗技K480 增加Home、End键

    最近看张大妈上很多人分享了我的桌面,有感于整天低头码字不利健康,隧鼓捣起自己的电脑桌了. 此处省略N字... 进入正文,我码字用的是罗技的K480蓝牙键盘 码了几行代码,发现没有Home.End键,这 ...

  7. layerui

    引用layer.js,官网:http://layer.layui.com/常用属性:btn/icon/skin/time/content/yes(点击确认.提交) 常用窗体.alert layer.a ...

  8. MVC基架生成的Create视图

    @model MyMusicStore.Models.Album @{     ViewBag.Title = "Create"; } <h2>Create</h ...

  9. AY的Dapper研究学习-继续深入-C#开发-aaronyang技术分享

    原文:AY的Dapper研究学习-继续深入-C#开发-aaronyang技术分享 ====================www.ayjs.net       杨洋    wpfui.com      ...

  10. laravel 报错SQLSTATE[HY000] [2002] No such file or directory

    在mac中执行php artisan migrate时报错 SQLSTATE[HY000] [2002] No such file or directory (SQL: select * from i ...