在这篇martin和另外两位模式匹配领域专家的论文里说了模式匹配的几种实现方式,以及scala是选择哪种方式来实现的。
http://lampwww.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf
我引用了里面的一些描述。

在面向对象的程序中数据被组织为一级一级的类(class)
面向对象语言在模式匹配方面的问题在于如何从外部探测这个层级。

有6种实现模式匹配的方法:
1) 面向对象的分解 (decomposition)
2) 访问器模式 (visitor)
3) 类型测试/类型造型 (type-test/type-cast)
4) typecase
5) 样本类 (case class)
6) 抽取器 (extractor)

论文里从3个维度9个标准来对比了各种实现方式:
简明程度(框架支持、浅匹配、深匹配),维护性(表征独立、扩展性),性能(基础性能、广度和深度延展性)


比较的细节在这篇论文里有提,不一一展开。
最终scala选择了采用 样本类(case class) 和 抽取器(extractor) 来实现模式匹配。

我们大致了解一下case class和extractor 是怎么回事

1)样本类(case class)

本质上case class是个语法糖,对你的类构造参数增加了getter访问,还有toString, hashCode, equals 等方法;
最重要的是帮你实现了一个伴生对象,这个伴生对象里定义了apply 方法和 unapply 方法。
apply方法是用于在构造对象时,减少new关键字;而unapply方法则是为模式匹配所服务。
这两个方法可以看做两个相反的行为,apply是构造(工厂模式),unapply是分解(解构模式)。

case class在暴露了它的构造方式,所以要注意应用场景:当我们想要把某个类型暴露给客户,但又想要隐藏其数据表征时不适宜。

2) 抽取器(extrator)

抽取器是指定义了unapply方法的object。在进行模式匹配的时候会调用该方法。
unapply方法接受一个数据类型,返回另一数据类型,表示可以把入参的数据解构为返回的数据。

比如
class A
class B(val a:A)
object TT {
def unapply(b:B) = Some(new A)
}
这样定义了抽取器TT后,看看模式匹配:val b = new B(new A); b match{ case TT(a) => println(a) }
直观上以为 要拿b和TT类型匹配,实际被翻译为 TT.unapply(b)  match{ case Some(…) => … }

它与上面的case class相比,相当于自己手动实现unapply,这也带来了灵活性。
后续会专门介绍一下extrator,这里先看一下extractor怎么实现case class无法实现的”表征独立”(representation independence)

比如我们想要暴露的类型为A

//定义为抽象类型
trait A

//然后再实现一个具体的子类,有2个构造参数
class B (val p1:String, val p2:String) extends A

//定义一个抽取器
object MM{

//抽取器中apply方法是可选的,这里是为了方便构造A的实例
def apply(p1:String, p2:String) : A = new B(p1,p2);

//把A分解为(String,String)
def unapply(a:A) : Option[(String, String)] = {
if (a.isInstanceOf[B]) {
val b = a.asInstanceOf[B]
return Some(b.p1, b.p2)
}
None
}
}

这样客户只需要通过 MM(x,y) 来构造和模式匹配了。客户只需要和MM这个工厂/解构角色打交道,A的实现怎么改变都不受影响。

注:
有很多的资料里在介绍case class时经常把它和函数式语言里的代数数据类对比(ADT)
严格的说Scala中的case class并不是ADT,但比较靠近,可以模拟ADT。
这篇文章中提到case class介于类继承和代数数据类型之间 http://blog.csdn.net/jinxfei/article/details/4677359
提到:”Scala则提供了一种介于两者之间(类继承和代数数据类型),被称为条件类(case classes)的概念”

《Programming in Scala》中文版,在术语表中有提到ADT:
通过提供若干个含有独立构造器的备选项(alternative)来定义的类型。通常可以辅助于通过模式匹配解构类型的方式。
这个概念可以在规约语言和函数式语言中发现。代数数据类型在Scala中可以用样本类(case class)模拟。

转自:http://ifeve.com/pattern-matching-2/

scala 模式匹配详解 2 scala里是怎么实现的?的更多相关文章

  1. scala 模式匹配详解 1

    什么是模式? 一些刚从java转到scala的同学在开发的过程中犹如深陷沼泽,因为很多的概念或风格不确定,scala里有很多的坑,模式匹配也算一个.我整理了一下自己所理解的概念,以及一些例子.这个系列 ...

  2. scala 模式匹配详解 3 模式匹配的核心功能是解构

    http://www.artima.com/scalazine/articles/pattern_matching.html这篇文章是odersky谈scala中的模式匹配的一段对话,我做了部分片段翻 ...

  3. Scala 入门详解

    Scala 入门详解 基本语法 Scala 与 Java 的最大区别是:Scala 语句末尾的分号 ; 是可选的 Scala 程序是对象的集合,通过调用彼此的方法来实现消息传递.类,对象,方法,实例变 ...

  4. KMP字符串模式匹配详解(zz)

    刚看到位兄弟也贴了份KMP算法说明,但本人觉得说的不是很详细,当初我在看这个算法的时候也看的头晕昏昏的,我贴的这份也是网上找的.且听详细分解: KMP字符串模式匹配详解 来自CSDN     A_B_ ...

  5. KMP字符串模式匹配详解

    KMP字符串模式匹配详解 http://www.cppblog.com/oosky/archive/2006/07/06/9486.html

  6. Spark入门到精通--(第二节)Scala编程详解基础语法

    Scala是什么? Scala是以实现scaleable language为初衷设计出来的一门语言.官方中,称它是object-oriented language和functional languag ...

  7. Scala入门详解

    object作为Scala中的一个关键字,相当于Java中的public static class这样的一个修饰符,也就说object中的成员都是静态的! 所以我们在这个例子中的main方法是静态的, ...

  8. Scala集合类详解

    对scala中的集合类虽然有使用,但是一直处于一知半解的状态.尤其是与java中各种集合类的混合使用,虽然用过很多次,但是一直也没有做比较深入的了解与分析.正好趁着最近项目的需要,加上稍微有点时间,特 ...

  9. Scala面向对象详解

    Scala的包(作用域) package com.jh.scala 等同于 package jh \n package scala 等同于 package com.jh{ package scala ...

随机推荐

  1. Mybatis 中遍历map 参数中的 list 和 array 属性

    原文:https://blog.csdn.net/liudongdong0909/article/details/51048835 问题在项目有中遇到批量删除操作时,需要根据两个属性去删除数据,其中一 ...

  2. EBS R12视图打不到数据

    兩個原因引起的,一個是語言,一個是oualter session set nls_language ='AMERICAN';alter session set nls_language='SIMPLI ...

  3. Java中有哪些语法糖?

    不要你写汇编,Java句句是糖 不能同意上面的这句话,要说为什么,首先要定义下面要讲的“语法糖”. 语法糖指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,并没有给语言添加什么新东西,但是 ...

  4. Android GUI之View绘制流程

    在上篇文章中,我们通过跟踪源码,我们了解了Activity.Window.DecorView以及View之间的关系(查看文章:http://www.cnblogs.com/jerehedu/p/460 ...

  5. cocos2d-x 开发用到的工具

    1.VertexHelper 可用于多边形顶点的计算,可视化定点编辑器,用它创建的顶点信息可以直接导出为Box2D可使用的代码 https://github.com/jfahrenkrug/Verte ...

  6. 【NIO】Java NIO之缓冲

    一.前言 在笔者打算学习Netty框架时,发现很有必要先学习NIO,因此便有了本博文,首先介绍的是NIO中的缓冲. 二.缓冲 2.1 层次结构图 除了布尔类型外,其他基本类型都有相对应的缓冲区类,其继 ...

  7. 【HTML打印】HTML直接调用window下的打印机并执行打印任务(简单打印任务生成)

    1.<button onclick="preview('data');" id="print">打印</button> 2. 3.js: ...

  8. 自动化测试中CSS SELECTOR选择器的一些写法

    常见符号: #表示id .表示class >表示子元素,层级 一个空格也表示子元素,但是是所有的后代子元素,相当于xpath中的相对路径 #input 选择id为input的节点 .Volvo ...

  9. 如何将Ubuntu Server 12.04 升级到 Ubuntu Server 14.04 LTS

    升级Ubuntu 12.04到Ubuntu 14.04方法如下: 步骤一:在终端中运行下面的命令,它将安装所有的升级包.$ sudo apt-get update && sudo ap ...

  10. git checkout -b mybranch和git checkout mybranch

      创建分支: $ git branch mybranch切换分支: $ git checkout mybranch创建并切换分支: $ git checkout -b mybranch更新maste ...