7.    模式匹配和样例类

Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句、类型检查等。并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配。

7.1.   匹配字符串

  1. package cn.itcast.cases
  2. import scala.util.Random

  3. object CaseDemo01 extends App{
  4.   val arr = Array("hadoop", "zookeeper", "spark")
  5.   val name = arr(Random.nextInt(arr.length))
  6.   name match {
  7.     case "hadoop"    => println("大数据分布式存储和计算框架...")
  8.     case "zookeeper" => println("大数据分布式协调服务框架...")
  1.     case "spark" => println("大数据分布式内存计算框架...")
  2.     case _ => println("我不认识你...")
  3.   }
  4. }
  1.  

7.2.   匹配类型

  1. package cn.itcast.cases
  2. import scala.util.Random

  3. object CaseDemo01 extends App{
  4.   val arr = Array("hello", 1, 2.0, CaseDemo)
  5.   val v = arr(Random.nextInt(4))
  6.   println(v)
  7.   v match {
  8.     case x: Int => println("Int " + x)
  9.     case y: Double if(y >= 0) => println("Double "+ y)
  10.     case z: String => println("String " + z)
  11.     case _ => throw new Exception("not match exception")
  12.   }
  13. }
  1.  

注意case y: Double if(y >= 0) => ...

模式匹配的时候还可以添加守卫条件。如不符合守卫条件,将掉入case _中。

7.3.   匹配数组、元组、集合

  1. package cn.itcast.cases

  2. object CaseDemo03 extends App{
  3.  
  4.   val arr = Array(1, 3, 5)
  5.   arr match {
  6.     case Array(1, x, y) => println(x + " " + y)
  7.     case Array(0) => println("only 0")
  8.     case Array(0, _*) => println("0 ...")
  9.     case _ => println("something else")
  10.   }
  11.  
  12.   val lst = List(3, -1)
  13.   lst match {
  14.     case 0 :: Nil => println("only 0")
  15.     case x :: y :: Nil => println(s"x: $x y: $y")
  16.     case 0 :: tail => println("0 ...")
  17.     case _ => println("something else")
  18.   }
  19.  
  20.   val tup = (1, 3, 7)
  21.   tup match {
  22.     case (1, x, y) => println(s"1, $x , $y")
  23.     case (_, z, 5) => println(z)
  24.     case  _ => println("else")
  25.   }
  26. }
  1.  

注意:在Scala中列表要么为空(Nil表示空列表)要么是一个head元素加上一个tail列表。

9 :: List(5, 2)  :: 操作符是将给定的头和尾创建一个新的列表

注意::: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于 9 :: (5 :: (2 :: Nil))

7.4.   样例类

在Scala中样例类是一种特殊的类,可用于模式匹配。

定义形式:

case class 类型,是多例的,后面要跟构造参数。 case class Student(name:String)

case object 类型,是单例的。        case object Person

  1. package cn.itcast.cases
  2. import scala.util.Random

  1. case class SubmitTask(id: String, name: String)
  2. case class HeartBeat(time: Long)
  3. case object CheckTimeOutTask
  4.  
  5. object CaseDemo04 extends App{
  6.   val arr = Array(CheckTimeOutTask, HeartBeat(12333), SubmitTask("0001", "task-0001"))
  7.  
  8.   arr(Random.nextInt(arr.length)) match {
  9.     case SubmitTask(id, name) => {
  10.       println(s"$id, $name")
  11.     }
  12.     case HeartBeat(time) => {
  13.       println(time)
  14.     }
  15.     case CheckTimeOutTask => {
  16.       println("check")
  17.     }
  18.   }
  19. }
  1.  

7.5.   Option类型

在Scala中Option类型用样例类来表示可能存在或者可能不存在的值(Option的子类有Some和None)。Some包装了某个值,None表示没有值

  1. package cn.itcast.cases
  2.  
  3. object OptionDemo {
  4.   def main(args: Array[String]) {
  5.     val map = Map("a" -> 1, "b" -> 2)
  6.     val v = map.get("b") match {
  7.       case Some(i) => i
  8.       case None => 0
  9.     }
  10.     println(v)
  11.     //更好的方式
  12.     val v1 = map.getOrElse("c", 0)
  13.     println(v1)
  14.   }
  15. }
  1.  

7.6.   偏函数

被包在花括号内没有match的一组case语句是一个偏函数,它是PartialFunction[A, B]的一个实例,A代表输入参数类型,B代表返回结果类型,常用作输入模式匹配,偏函数最大的特点就是它只接受和处理其参数定义域的一个子集。

  1. package cn.itcast.cases

  2. object PartialFuncDemo  {
  3.  
  4.   valfunc1: PartialFunction[String, Int] = {
  5.     case "one" => 1
  6.     case "two" => 2
  7.     case _ => -1
  8.   }
  1.   def func2(num: String) : Int = num match {
  2.     case "one" => 1
  3.     case "two" => 2
  4.     case _ => -1
  5.   }
  1.   def main(args: Array[String]) {
  2.     println(func1("one"))
  3.     println(func2("one"))
  4.   }
  5. }

8.    Scala中的协变、逆变、非变

8.1.   协变、逆变、非变介绍

Array[String]   Array[Object]

协变和逆变主要是用来解决参数化类型的泛化问题。Scala的协变与逆变是非常有特色的,完全解决了Java中泛型的一大缺憾;举例来说,Java中,如果有 A是 B的子类,但 Card[A] 却不是 Card[B] 的子类;而 Scala 中,只要灵活使用协变与逆变,就可以解决此类 Java 泛型问题;

由于参数化类型的参数(参数类型)是可变的,当两个参数化类型的参数是继承关系(可泛化),那被参数化的类型是否也可以泛化呢?Java中这种情况下是不可泛化的,然而Scala提供了三个选择,即协变(“+”)、逆变(“-”)和非变。

下面说一下三种情况的含义,首先假设有参数化特征Queue,那它可以有如下三种定义。

(1)  trait Queue[T] {}

这是非变情况。这种情况下,当类型B是类型A的子类型,则Queue[B]与Queue[A]没有任何从属关系,这种情况是和Java一样的。

(2)  trait Queue[+T] {} 
         这是协变情况。这种情况下,当类型B是类型A的子类型,则Queue[B]也可以认为是Queue[A]的子类型,即Queue[B]可以泛化为Queue[A]。也就是被参数化类型的泛化方向与参数类型的方向是一致的,所以称为协变。

(3)   trait Queue[-T] {}

这是逆变情况。这种情况下,当类型B是类型A的子类型,则Queue[A]反过来可以认为是Queue[B]的子类型。也就是被参数化类型的泛化方向与参数类型的方向是相反的,所以称为逆变。

8.2.   协变、逆变、非变总结

  • C[+T]:如果A是B的子类,那么C[A]是C[B]的子类。
  • C[-T]:如果A是B的子类,那么C[B]是C[A]的子类。
  • C[T]: 无论A和B是什么关系,C[A]和C[B]没有从属关系。

8.3.   案例

  1. package cn.itcast.scala.enhance.covariance

  2. class Super
  3. class Sub extends Super
  4. //协变
  5. class Temp1[+A](title: String)
  6. //逆变
  7. class Temp2[-A](title: String)
  8. //非变
  9. class Temp3[A](title: String)
  10.  
  11. object Covariance_demo{
  12.   def main(args: Array[String]) {
  13.     //支持协变 Temp1[Sub]还是Temp1[Super]的子类
  14.     val t1: Temp1[Super] = new Temp1[Sub]("hello scala!!!")
  15.     //支持逆变 Temp1[Super]是Temp1[Sub]的子类
  16.     val t2: Temp2[Sub] = new Temp2[Super]("hello scala!!!")
  17.     //支持非变 Temp3[Super]与Temp3[Sub]没有从属关系,如下代码会报错
  18.     //val t3: Temp3[Sub] = new Temp3[Super]("hello scala!!!")
  1. //val t4: Temp3[Super] = new Temp3[Sub]("hello scala!!!")
  2.     println(t1.toString)
  3.     println(t2.toString)
  4.   }
  5. }

9.    Scala中的上下界

9.1.  上界、下界介绍

Java中:

?  extends  T :上界,表示参数类型?必须是某个类型T或T的子类;

?  super  T :下界,表示参数类型?必须是某个类型T或T的父类。

在指定泛型类型时,有时需要界定泛型类型的范围,而不是接收任意类型。比如,要求某个泛型类型,必须是某个类的子类,这样在程序中就可以放心的调用父类的方法,程序才能正常的使用与运行。此时,就可以使用上下边界Bounds的特性;

Scala的上下边界特性允许泛型类型是某个类的子类,或者是某个类的父类;

(1) U >: T     ?  super  T

这是类型下界的定义,也就是U必须是类型T的父类(或本身,自己也可以认为是自己的父类)。

(2) S <: T    ?  extends T

这是类型上界的定义,也就是S必须是类型T的子类(或本身,自己也可以认为是自己的子类)。

第3节 Scala中的模式匹配:1 - 5的更多相关文章

  1. 第74讲:从Spark源码的角度思考Scala中的模式匹配

    今天跟随王老师学习了从源码角度去分析scala中的模式匹配的功能.让我们看看源码中的这一段模式匹配: 从代码中我们可以看到,case RegisterWorker(id,workerHost,.... ...

  2. (数据科学学习手札49)Scala中的模式匹配

    一.简介 Scala中的模式匹配类似Java中的switch语句,且更加稳健,本文就将针对Scala中模式匹配的一些基本实例进行介绍: 二.Scala中的模式匹配 2.1 基本格式 Scala中模式匹 ...

  3. 第4节 Scala中的actor介绍:1、actor概念介绍;2、actor执行顺序和发送消息的方式

    10.    Scala Actor并发编程 10.1.   课程目标 10.1.1.    目标一:熟悉Scala Actor并发编程 10.1.2.    目标二:为学习Akka做准备 注:Sca ...

  4. 第2节 Scala中面向对象编程:12、13、14、15、16、trait

    6.4.  Scala中面向对象编程之trait 6.4.1.    将trait作为接口使用 Scala中的trait是一种特殊的概念: 首先先将trait作为接口使用,此时的trait就与Java ...

  5. 第2节 Scala中面向对象编程:9、getClass和classOf;10、调用父类的constructor;11、抽象类和抽象字段;

    6.3.4.     Scala中getClass 和 classOf Class A extends class B B b=new A    b.getClass ==classOf[A] B b ...

  6. 第2节 Scala中面向对象编程:7、继承的概念以及override和super关键字;8、isInstanceOf 和 asInstanceOf关键字

    6.3.   Scala面向对象编程之继承 6.3.1.     Scala中继承(extends)的概念 Scala 中,让子类继承父类,与 Java 一样,也是使用 extends 关键字: 继承 ...

  7. 第2节 Scala中面向对象编程:1、类的定义;2、类的构造器;3、object和伴生对象;4、apply和main方法

    6.    类.对象.继承.特质 Scala的类与Java.C++的类比起来更简洁,学完之后你会更爱Scala!!! 6.1.   类 6.1.1.    类的定义 package cn.itcast ...

  8. scala中的模式匹配

    基本语法 变量 match { case 值1 => 代码 case 值2 => 代码 ... case 值N if (...) => 代码 case _ => 代码 } 常量 ...

  9. Scala入门到精通——第十五节 Case Class与模式匹配(二)

    本节主要内容 模式匹配的类型 for控制结构中的模式匹配 option类型模式匹配 1. 模式的类型 1 常量模式 object ConstantPattern{ def main(args: Arr ...

随机推荐

  1. Getopt::Long - Extended processing of command line options

    use Getopt::Long; my $data   = "file.dat"; my $length = 24; my $verbose; GetOptions (" ...

  2. 计算机二级-C语言-程序填空题-190107记录

    //给定程序的功能是:调用fun函数建立班级通讯录.通讯中记录每位学生的编号,姓名和电话号码.班级的人数和学生的信息从键盘读入,每个人的信息作为一个数据块(代表要使用结构体)写到名为myfile5.d ...

  3. 萌新深度学习与Pytorch入门记录(一):Win10下环境安装

    深度学习从入门到入土,安装软件及配置环境踩了不少坑,过程中参考了多处博主给的解决方法,遂整合一下自己的采坑记录. (若遇到不一样的错误,请参考其他博主答案解决) 笔者电脑系统为win10系统,在此环境 ...

  4. Coursera-吴恩达机器学习课程笔记-Week1

    参考资料: 吴恩达教授机器学习课程 机器学习课程中文笔记 Week 1 一. 引言 机器学习模型可分为监督学习Superviese learning(每个数据集给出了正确的值)和无监督学习Unsupe ...

  5. UTC/GMT/CST/RTC

    GMT:格林尼治标准时间,是指位于伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线.也就是零时区的时间. UTC:世界协调时间,是一个时间系统.可以理解为这个地球的标准时间 ...

  6. Git主库私库相关操作操作

    命令1: git remote add 库名称 库地址 说明:写好的代码提交到两个git远端,git remote add是将另一个库地址设置进来 命令2: git fetch 库名称 分支名称 说明 ...

  7. 2000G电脑大型单机游戏合集

    激活码 游戏名称(ctrl+F查找) 下载链接005875 艾迪芬奇的记忆 游戏下载链接http://pan.baidu.com/s/1t2PYRAj546_1AcOB-khJZg554158 暗影: ...

  8. 分布式事务 --- CAP 理论

    本文部分来自参考资料!!半原创 概述 介绍CAP理论,并简单地证明了三存二的定论. CAP 理论 1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标.分别为 : C ...

  9. HDU 2063 过山车(二分图 && 匈牙利 && 最小点覆盖)

    嗯... 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063 这是一道很经典的匈牙利问题: 把男同学看成左边点,女同学看成右边点,如果两个同学愿意同 ...

  10. python3.8的PySimpleGUI学习的温度转换(℃转℉)

    一.代码1: #导出模块 import PySimpleGUI as sg #总体布局,sg.InputText(),默认size=(45,1). layout = [ [sg.Text('Celci ...