zoukankan      html  css  js  c++  java
  • 【转】Scala学习——模式匹配和样例类

    原文链接 http://nerd-is.in/2013-09/scala-learning-pattern-matching-and-case-classes/

    原文发表于:http://nerd-is.in/2013-09/scala-learning-pattern-matching-and-case-classes/

    Scala强大的模式匹配机制,可以应用在switch语句、类型检查以及“析构”等场合。

    样例类对模式匹配进行了优化。

    更好的switch

     

    上面代码中,case _模式对应于switch语句中的default,能够捕获剩余的情况

    如果没有模式能匹配,会抛出MatchError。而且不像常见的switch语句,

    在一种模式匹配之后,需要使用break来声明分支不会进入下一个分支。

    match是表达式,不是语句,所以是有返回值的,故可将代码简化:

    match表达式中可以使用任何类型。模式总是从上往下进行匹配。

    守卫

    看代码就好,与if表达式的守卫相同作用:

     

    模式中的变量

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

    case _是这个特性的一个特殊情况,变量名是_。

    经过我的尝试,在如果变量名是_,那么在=>后使用_是不行的。

    在模式中使用变量可能会与常量冲突。

    在上面的代码中,要如何判断Pi这个标志符是一个用来匹配的常量还是模式中的变量?

    规则是:变量比需要以小写字母开始。如果有常量是小写字母开头的,那么需要用反引号将常量名包起来:

     

    类型模式

    相比使用isInstanceOf来判断类型,使用模式匹配更好。

    在匹配类型时,需要使用一个变量名,否则就是使用对象本身来进行匹配了

    因为匹配是发生在运行期的,而且JVM中泛型的类型信息会被擦掉,

    此不能使用类型来匹配特定的Map类型(大部分集合类型也都不可以吧):

    但对于数组来说,类型信息是完好的,所以可以在Array上匹配。

    匹配数组、列表和元组

     

    下面的模式匹配,功能与上面的代码是一样的,不过将数组换成了列表。

    与上面两个例子差不多,模式匹配也可以使用在元组上。

    注意到变量将会被绑定到这三种数据结构的不同部分上,这种操作被称为“析构”。

    提取器

    在上一节中,使用模式匹配来对数组、列表和元组进行了匹配,在这个过程的背后的是提取器(extractor)机制。

    使用unapply来提取固定数量的对象,使用unapplySeq来提取一个序列。

    在前面的代码

     case Array(0, x) => ...中, Array(0, x)部分实际上是使用了伴生对象中的提取器,实际调用形式是: Array.unapplySeq(arr)。

    根据Doc,提取器方法接受一个Array参数,返回一个Option。

    正则表达式是另一个适用提取器的场景。正则有分组时,可以用提取器来匹配分组:

     

    变量声明中的模式

    在变量声明中的模式对于返回对偶(更广一点也可以用在元组上吧?)的函数来说很有用。

     

    for表达式中的模式

    这一部分的内容多在介绍for表达式时提过了,不过当时并没有意识到使用的是模式。

     

    样例类

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

    使用:

    在声明样例类时,下面的过程自动发生了:

    • 构造器的每个参数都成为val,除非显式被声明为var,但是并不推荐这么做;
    • 在伴生对象中提供了apply方法,所以可以不使用new关键字就可构建对象
    • 提供unapply方法使模式匹配可以工作
    • 生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义

    除了上述之外,样例类和其他类型完全一样,方法字段等。

    copy方法和带名参数

    样例类的copy方法创建一个与现有对象相同的新对象。可以使用带名参数来修改某些属性

     

    case语句中的中置表示法

    如果unapply方法产出一个对偶,则可以在case语句中使用中置表示法

    对于有两个参数的样例类,可以使用中置表示法。

    这个特性的本意是要匹配序列。举例,List对象要么是Nil,要么是样例类::。所以可以:

    多个中置表达式放在一起时会比普通的形式更加易读。

    匹配嵌套结构

    这个解释起来有点绕。

    模式可以匹配到特定的嵌套:

    上面的代码中descr这个变量被绑定到第一个Article的description。另外还可以使用@来将值绑定到变量

    下面是个使用了模式匹配来递归计算Item价格的函数。

     

    密封类

    当使用样例类来做模式匹配时,如果要让编译器确保已经列出所有可能的选择,

    可以将样例类的通用超类声明为sealed。

    密封类的所有子类都必须在与该密封类相同的文件中定义。

    如果某个类是密封的,那么在编译期所有的子类是可知的,因而可以检查模式语句的完整性。

    让所有同一组的样例类都扩展某个密封的类或特质是个好的做法。

    模拟枚举

    可以使用样例类来模拟枚举类型:

     

    Option类型

    Option类型用来表示可能存在也可能不存在的值。样例子类Some包装了某个值,而样例对象None表示没有值。

    Option支持泛型。

     

    偏函数(L2)

    被包在花括号内的一组case语句是一个偏函数。

    偏函数是一个并非对所有输入值都有定义的函数,是PartialFunction[A, B]类的一个实例,

    其中A是参数类型,B是返回类型。该类有两个方法:apply方法从匹配的模式计算函数值;

    isDefinedAt方法在输入至少匹配其中一个模式时返回true。

     


    本章练习参考

  • 相关阅读:
    浮动 无刷新 div
    vidalia 更换浏览器代理
    vb 主动 点击 a
    Delphi 资料收集
    用Linux的iptables和Python模拟广域网
    框架资源
    div 边框
    Google App Engine
    mac 雪豹 10.6 五国
    Windows Azure Storage (3) Windows Azure Storage Service存储服务之Blob详解(中)
  • 原文地址:https://www.cnblogs.com/ihongyan/p/4811958.html
Copyright © 2011-2022 走看看