`
wbj0110
  • 浏览: 1598442 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Scala——模式匹配和样例类

阅读更多

原文发表于: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。

 

 

分享到:
评论

相关推荐

    scala的匹配样例类

    scala可以使用模式匹配来匹配样例类,从而可以快速获取样例类中的成员数据。后续,我们在开发Akka案例时,还会用到。 示例 需求说明 创建两个样例类Customer、Order Customer包含姓名、年龄字段 Order包含id字段 ...

    scala语言for循环中的模式匹配

    本文将详细介绍 Scala 语言 for 循环中的六种模式匹配方式:变量模式匹配、常量模式匹配、变量绑定模式匹配、类型模式匹配、构造函数模式匹配和序列模式匹配。 变量模式匹配 在 Scala 语言中,变量模式匹配是最...

    scala正则表达式与模式匹配.doc

    Scala 正则表达式是 Scala 语言中的一种强大工具,用于模式匹配和字符串处理。在 Scala 中,正则表达式可以通过两种方式创建:通过 `r` 方法直接将字符串转换成正则表达式对象,或者直接显式地调用 `Regex` 构造函数...

    大数据课程-Scala编程基础-5.Scala模式匹配_lk_edit.ppt

    例如,函数`abs(x: Int)`使用模式匹配和条件守卫来判断一个整数是否为正数或负数,并返回其绝对值。 ```scala def abs(x: Int) = x match { case i: Int if i >= 0 => i case j: Int if j < 0 => -j case _ => ...

    Scala样例类练习.docx

    在Scala中,样例类(Case Class)是一种特殊类型的类,主要用于模式匹配和不可变数据结构的构建。它们提供了许多便利的功能,如自动实现`equals`、`hashCode`、`toString`等方法,简化了开发者的编码工作量。 #### ...

    scala pattern match

    1. **案例类(Case Classes)**:这是Scala中一种特殊的类,主要用于模式匹配。它们自动实现了`equals`和`hashCode`方法,以及`toString`方法,非常适合用作模式匹配中的模式。 2. **提取器(Extractors)**:在...

    Scala模式匹配.md

    Scala模式匹配.md

    4.样式类和模式匹配1

    模式匹配和 Java 的 `switch` 语句类似,但更加强大,因为它可以处理更复杂的结构,而且是一个表达式,总是返回一个值。`@unchecked` 注解用于抑制未覆盖模式的检查,防止 `MatchError` 异常。 总的来说,样例类和...

    scala连接redis哨兵模式 demo 使用scala的redis库(csdn)————程序.pdf

    5. 数据操作:通过实例化后的SentinelMonitoredRedisClient对象,程序可以执行基本的Redis操作,例如设置键值对、获取键值对、检索匹配特定模式的键集等。 6. 异步执行与等待结果:代码示例展示了如何使用Await等待...

    Scala和设计模式.pdf

    Scala作为一种兼具面向对象和函数式编程特性的现代语言,通过一系列高级语言特性(如模式匹配、类型推断等)使得许多设计模式的实现更加简洁高效。 #### 二、Scala中的设计模式 接下来,我们将具体介绍几种在Scala...

    Scala设计模式

    通过以上几种设计模式的例子可以看出,Scala支持各种面向对象和函数式的设计模式,这些模式有助于编写更高质量、更灵活、更容易维护的代码。在实际开发中,根据项目的具体需求选择合适的设计模式是非常重要的。

    快学 scala 语法大全

    此文档是scala的语法大全,一共分为22章,控制结构,特质,高阶函数,集合,模式匹配,样例类,解析,actor等都包括在内。

    Scala—— 3.函数

    函数式编程把函数当作一等公民,充分利用函数、只是函数的多种使用方式,在Scala中,函数是一等公民,像变量一样,既可以作为函数的参数使用,也可以将函数赋值给一个变量,函数的创建不用依赖于类或者对象,而在...

    Scala 专题教程 - Case Class和模式匹配-内含源码以及设计说明书(可以自己运行复现).zip

    在Scala中,Case Class是一种特殊的类,它被设计用于模式匹配和数据封装。其特点包括: 1. **自动成员访问**:Case Class的成员默认是公开的,可以直接通过`.`操作符访问。 2. **隐式拷贝功能**:创建Case Class...

    浅谈Scala模式匹配

    Scala 模式匹配是 Scala 语言中的一种强大语言特性,它允许开发者通过模式匹配来处理不同的数据类型和值。模式匹配的基本语法是 `e match { case Pattern1 => do Something case Pattern2 if-clause => do others .....

    Scala中正则表达式以及与模式匹配结合(多种方式)

    例如,可以根据不同条件匹配和执行不同的操作。 综上所述,Scala中的正则表达式及其与模式匹配的结合,为字符串处理提供了一种强大而灵活的工具。无论是在简单的文本解析还是在复杂的模式匹配场景中,Scala都提供了...

    《快学Scala》完整版书籍.rar

    12. **模式匹配和样例类**:模式匹配用于解构复杂数据结构,如匹配枚举值、拆解元组等。样例类(Case Class)是Scala中用于简化模式匹配的特殊类,具有默认的构造函数、equals、hashCode和toString方法。 通过学习...

    Scala—— 2. 流程控制

    值得注意的是,Scala没有Java中的`switch`语句,但可以用模式匹配(`match-case`)来达到类似的效果。 对于循环,Scala提供多种循环形式。基础的`for`循环可以迭代范围或集合,如: ```scala for (i ) println(i) ```...

    Scala编程详解 第18讲-Scala编程详解:模式匹配 共11页.pptx

    共13页第15讲-Scala编程详解:面向对象编程之Trait 共14页第16讲-Scala编程详解:函数式编程 共14页第17讲-Scala编程详解:函数式编程之集合操作 共9页第18讲-Scala编程详解:模式匹配 共11页第19讲-Scala编程详解:...

    Scala—— 9.伴生对象apply方法

    在Scala编程语言中,伴生对象(Companion Object)与类有着独特的关联关系,它们可以在同一个源文件中定义,共享类的私有信息。伴生对象可以看作是类的一个朋友,它能访问类的私有成员,同时也能提供一些便利的方法...

Global site tag (gtag.js) - Google Analytics