一.本章要点

  • match表达式是更好的switch,不会有意外调入下一个分支
  • 如果没有模式能够匹配,会抛出MatchError,可以用case _模式避免
  • 模式可以包含一个随意定义的条件,称做守卫
  • 你可以对表达式的类型进行匹配;优先选择模式匹配而不是isInstanceOf/asInstanceOf
  • 你可以匹配数组,元祖,样例类的模式,然后匹配到不同部分绑定到变量
  • 在for表达式中,不能呢匹配的情况会被安静的跳过
  • 样例类是编译器会为之自动

二.更好的switch

  

var sign=...
val ch:Char=...
ch match{
case '+'=>sign=1
case '-'=>sign=-1
case _=>sign=0
}
//简写
sign=ch match{
....
}

三.守卫

  添加守卫做筛选条件,例:

ch match{
case '+'=>sign=1
case '-'=>sign=-1
//筛选所有数字
case _ if Charavter.isDigit(ch)=>digit=Character.digit(ch,10)
case _=>sign=0
}

四.模式中的变量

  如果case关键字后面跟着一个变量名,那么匹配的表达式会被赋值给那个变量。例如:

str(i) match{
case '+'=>sign=1
...
case ch=>Character.digt(ch,10)
}

五.类型模式

  对表达式的类型进行匹配,例:

obj match{
case x:Int=>x
case s:String=>Integer.parseInt(s)
case _:BigInt=>Int.MaxValue
case _=>'0'
}

  注:在Scala中,更倾向与使用这样的匹配模式,而不是isInstanceOf操作符;

    匹配时,必须给出一个变量名,否则会拿对象本身匹配;

    匹配发生在运行期,Java虚拟机的泛型是擦掉的,因此不能用类型匹配特定的Map类型  

六.匹配数组、列表和元祖

  匹配数组:

arr match{
//通过这种绑定让你轻松的访问复杂结构各部份名:”析构“
//匹配包含0的数组
case Array(0)=>"0"
//匹配任何带有两个元素的数组,并将这两个元素分别绑定在x和y
case Array(x,y)=>x+" "+y
//匹配任何以0开始的数组
case Array(0,_*)=>"0..."
case _=>"someting else"
}

  使用List表达式或者::匹配列表:

lst match{
case 0::Nil=>"0"
case x::y::Nil=>x+" "+y
case 0::tail=>"0..."
case _=>"something else"
}

  匹配元组:

pair match{
case (0,)=>"0..."
case (y,0)=>y+"0"
case _=>"neither is 0"
}

七.提取器

  前面的匹配数组,列表,元组功能背后的机制:提取器机制——带有对象中提取值的unapply或unapplySeq方法的对象。unapply方法提取固定数量的对象,unapplySeq提取一个序列。

  如:

arr match{
case Array(0,x)=>...
}

  Array伴生对象就是一个提取器——定义了一个unapplySeq方法,调用时是以被执行匹配动作的表达式作为参数,而不是模式上中看上去像是参数的表达式。unapplySeq(arr)产出一个序列的值,即数组的值。

  正则表达式是另一个适合用提取器的场景,注意这时的提取器不是伴生对象,而是正则表达式对象,例:正则表达式有分组时,匹配正则表达式分组

val pattern="([0-9]+) (a-z+)".r
"99 bottles" match{
case pattern(num,item)=>...
//num为99,item为bottles
}    

八.变量声明中的模式

  模式是可以带变量的,可以在变量声明时运用这样的模式,如 val (x,y)=(1,2)

//赋值商和余数
val (q,r)=BigInt(10) /%3 //将arr数组的第一个和第二个值分别赋给first和secend
val Array(first,secend,_)=arr

九.for表达式中的模式

  可以在for推导式使用带变量的模式。例:

import scala.collection.JavaConversions.propertiesAsScalaMap
for((k,v)<-System.getProperties()) println(k+"->"+v)

十.样例类

  样例类是一种特殊的类,经过优化用于模式匹配。

  例,扩展自常规类(非样例类)的样例类:

abstract class Amount
case class Dollar(value:Double) extends Amount
case class Currency(value:Double,unit:String) extends Amount //也可以针对单例的样例对象
case object Nothing extends Amount //当有一个类型为Amount的对象时,可以用模式匹配来匹配它的类型,并将属性绑定到变量
amt match{
case Dollar(v)=>"$"+v
case Currency(_,u)=>"Oh nose,I got"+u
case Nothing =>""
}

  注:样例类的实例使用(),样例对象不使用圆括号;

    当你声明样例类时,如下自动发生:

      • 构造器中的每一个参数都成为val——除非它是显示地声明为var(不建议这样做);
      • 在伴生对象中提供apply方法让你不用new关键字就能构造出相应的对象,如Dollar(29.25)...;
      • 提供unapply方法让模式可以工作;
      • 将生成toString、equals、hashCode和copy方法——除非显式地给出这些方法的定义;
      • 除这些,其他和普通的类一样

十一.copy方法和带名参数

  样例类的copy方法创建一个与现有对象值相同的新对象,原对象是不可变的,完全可以共享这个对象的引用,但是可以用带名参数修改某些属性,例:

val price=amt.copy(value=18.23)  

十二.case语句中的中置表示法

  如果unapply方法产生一个对偶,则你可以在case语句中使用中置表达式,例:

amt match{
case a Currency u=>...}//等同于case Currency(a,u)

十三.匹配嵌套结构

  样例类常被用于嵌套结构,例: 

abstract class Item
case class Article(description:String,price:Double) extends Item
case class Bundle(decription:String,discount:Double.item:Item*) extends Item

  使用@表示法将嵌套绑定到变量。

def price(it:Item):Double=it match{
case Article(_,p)=>P
case Bundle(_,disc,its @ _*)=>its.map(price _).sum-disc
}

十四.样例类是邪恶的吗

  样例类适用于那种标记不会改变的结构(如果是可改变的,那么如果想到一种新的Item,就需要回顾所有的item)。

  在合适的地方,样例类十分便捷:

      • 模式匹配通常比继承更容易把我们引向更精简的代码;
      • 构造时不需要用new的复合对象更加易读;
      • 你将免费得到toString、equals、hashCode和copy方法

十五.密封类

  通过将样例类的通用超类声明为sealed,可以确保列出所有的选择。

  密封类的子类都必须与该密封类相同的文件定义(好做法),如果某个类是密封的,那么在编译期所有子类是可知的,因此编译器可以检查模式语句的完整性。

十六.模拟枚举

  

十七.Option类型

  标准库中的Option类型用样例类来表示可能存在、也可能不存在的值。样例子类Some包装了某个值,例如:Some("Fred"),而样例对象None表示没有值(这种表示比使用空字符串的意图更加清晰,比使用null表示缺少的某值更加安全)。

  Option支持泛型,如Some("Fred")类型为Option[String]。Map类的get方法返回一个Option。

十八.偏函数

  被包在花括号内的一组case语句是一个偏函数——一个并非对所有输入都有定义的函数。它是PartialFunction[A,B]类的一个实例(A是参数类型,B是返回类型),该类有两个方法:apply从匹配的模式计算函数值,而isDefinedAt方法在输入至少匹配其中一个模式赶回true。

十九.练习

Scala学习十四——模式匹配和样例类的更多相关文章

  1. 【Scala篇】--Scala中Trait、模式匹配、样例类、Actor模型

    一.前述 Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大. 模式匹配机制相当于java中的switch-case. 使用了case关键字的类定义就是样例类(case ...

  2. Scala集合库、模式匹配和样例类

    package com.yz8 import org.junit.Test class test { @Test def test: Unit = { val ints = List(1,5,7,6, ...

  3. 学好Spark/Kafka必须要掌握的Scala技术点(二)类、单例/伴生对象、继承和trait,模式匹配、样例类(case class)

    3. 类.对象.继承和trait 3.1 类 3.1.1 类的定义 Scala中,可以在类中定义类.以在函数中定义函数.可以在类中定义object:可以在函数中定义类,类成员的缺省访问级别是:publ ...

  4. 大数据学习day16------第三阶段-----scala04--------1. 模式匹配和样例类 2 Akka通信框架

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

  5. Scala模式匹配和样例类

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

  6. Scala基础:模式匹配和样例类

    模式匹配 package com.zy.scala import scala.util.Random /** * 模式匹配 */ object CaseDemo { def main(args: Ar ...

  7. scala模式匹配与样例类

    样本类:添加了case的类便是样本类.这种修饰符可以让Scala编译器自动为这个类添加一些语法上的便捷设定.如下: 1.添加与类名一致的工厂方法.也就是说,可以写成Var("x") ...

  8. Scala学习十九——解析

    一.本章要点 文法定义中的二选一.拼接.选项和重复在Scala组合子解析器中对应|.~.opt和rep 对于RegexParsers而言,字符串字面量和正则表达式匹配的是词法单元 用^^来处理解析结果 ...

  9. Scala--模式匹配和样例类

    模式匹配应用场景:switch语句,类型查询,析构,样例类 一.更好的switch val ch :Char = '+' val sign = ch match{ case '+' => 1 c ...

随机推荐

  1. flask 设置配置文件的方式

    from flask import Flask from flask import current_app """ 配置参数设置与读取 """ ...

  2. Web开发中 MTV模式与MVC模式的区别 联系 概念

    MTV 与 MVC模式的区别 联系 概念: MTV: 所谓MTV指的就是: M:model (模型),指的是ORM模型. T:template (模板),一般Python都是使用模板渲染的方式来把HT ...

  3. windows下安装node.js及环境配置、部署项目

    windows下安装node.js及环境配置.部署项目 一.总结 一句话总结: 安装nodejs软件:就像普普通通的的软件那样安装 配置nodejs安装的全局模块的环境变量 并且安装cnpm(比如cn ...

  4. 定位ScheduledExecutorService过了一段时间不执行问题

    今天查看生产环境的sentinel控制台,发现某dubbo应用一共5个节点,有3个失联了. 查看失联节点的应用日志,服务没有挂,各dubbo接口的日志正常在打印. 在应用节点ping/telnet s ...

  5. Mysql触发器详解以及union的使用

    ---恢复内容开始--- Mysql触发器定义: 当一个表中有insert update delete事件发生,触发一个事件,执行一段代码.作用: 同步数据创建: create trigger 名称 ...

  6. [Oracle]关于回滚段的一些转贴摘录

    ORACLE 回滚段 回滚段概述 回滚段用于存放数据修改之前的值(包括数据修改之前的位置和值).回滚段的头部包含正在使用的该回滚段事务的信息.一个事务只能使用一个回滚段来存放它的回滚信息,而一个回滚段 ...

  7. mod 运算与乘法逆元

    mod 运算与乘法逆元 %运算 边乘边mod 乘法 除法 mod 希望计算5/2%7=6 乘法 除法 mod 希望计算5/2%7=6 两边同时/x 在取mod(p)运算下,a/b=a*bp-2 bp- ...

  8. Microsoft Office-未响应

    默认打印机的配置可能与 Word.Excel 打开文件一操作就未响应有关 今天写点文档突然发现 Word.Excel 打开文件一操作就未响应,新建一个文件编辑倒是没有问题,很奇怪.搜到的博客基本全是由 ...

  9. csv解析框架Windmill的一个demo

    csv文件内容如下,第一行是文件头 解析代码如下: package com.xxx; import lombok.Data; import org.apache.commons.lang3.build ...

  10. 通过route指令指定笔记本同时连接外网和内网

    假如你的外网网关是:X.X.X.X 内网网关:192.168.1.1 则在命令窗口输入以下两条命令: route add 0.0.0.0 mask 0.0.0.0 X.X.X.X route add ...