`
mabusyao
  • 浏览: 253496 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

(转)Case Class和模式匹配

 
阅读更多

(转自:http://www.tuicool.com/articles/amEBva)

 

本专题侧重介绍Scala的case class和pattern matching(模式匹配),这俩个两个程序结构对于处理树结构的数据非常有帮助。Scala的case class使得对对象进行模式匹配变得非常方便,简单的来说,Scala的case class就是在普通的类定义前加case这个关键字,然后你可以对这些类来模式匹配。 
在我们详细介绍Scala的Case class和模式匹配之前,我们可以通过一个简单的例子来说明一些基本概念。我们设计一个函数库,这个函数库可以用来计算算术表达式,为简单起见,我们设计的算术表达式只侧重于变量,数字,单操作符,和双操作符。我们可以采用如下的Scala类定义:

abstract class Expr
case class Var(name:String) extends Expr
case class Number(num:Double) extends Expr
case class UnOp(operator:String, arg:Expr) extends Expr
case class BinOp(operator:String,left:Expr,right:Expr) extends Expr

这里我们定义了一个抽象类Expr和四个子类(分别代表变量,数值,单操作符,双操作符),Scala允许我们不定义类的实现,实际我们是class C 和 class C {}是等价的。

case classes 
我们可以看到上面的四个子类定义前面我们使用了case关键字,使用了case关键字的类定义就是case classes。使用这个关键字,Scala编译器会自动为你定义的类生成一些成员。 
首先,编译器为case class生成一个同名的对象构造器(Factory Method),也就是你可以使用 Var(“x”) 来创建一个类的实例,而无需使用new Var(“x”).

scala> val x = Var("x")
x: Var = Var(x)

这个构造器在嵌套使用时显得非常简洁明了,比如 我们构建如下的表达式,这种写法避免了很多new 的使用。

scala> val op=BinOp("+",Number(1),x)
op: BinOp = BinOp(+,Number(1.0),Var(x))

其次,Scala编译器为case class的构造函数的参数创建以参数名为名称的属性,比如Val的类的参数name:String 可以直接通过 .name访问,比如:

scala> x.name
res1: String = x

第三,编译器为case class 构造了更自然的toString,hashCode和equals实现,它们会递归打印,比较case class的参数属性。比如:

scala> println(op)
BinOp(+,Number(1.0),Var(x))

scala> op.right == Var("x")
res3: Boolean = true

最后一点,Scala编译器为case class添加了一个Copy方法,这个copy方法可以用来构造类对象的一个可以修改的拷贝。这对于使用已有的对象构造一个新实例非常方便,你只要修新创建实例的某些参数即可。 
比如我们想创建一个和op类似的新的实例,只想修改+为-,可以使用:

scala> op.copy(operator="-")
res4: BinOp = BinOp(-,Number(1.0),Var(x))

以上这些惯例带来了很多便利,这些便利也需要一些小小的代价,就是需要在class前面使用case关键字,而构造后的类由于自动添加了一些方法而变大了些。case class带来的最大的好处是它们支持模式识别。

Pattern matching 
比如说你需要简化表达式的表示方法,这里给出一个简单的规则:

UnOp(“-”,Unop(“-”,e)) => e//负负得正 
BinOp(“+”,e,Number(0)) => e//和0加 
BinOp(”*”,e,Number(1)) => e //和1乘

使用模式匹配,在Scala我们几乎和使用和上面规则非常类似的代码来实现表达式的简化:

scala> def simplifyTop(expr :Expr) :Expr = expr match {
|   case UnOp("-",UnOp("-",e))=>e
|   case BinOp("+",e,Number(0))=>e
|   case BinOp("*",e,Number(1))=>e
|   case _ => expr
|	
| }
simplifyTop: (expr: Expr)Expr

scala> simplifyTop(UnOp("-",UnOp("-",Var("x"))))
res6: Expr = Var(x)

scala>

simplifyTop 定义使用了match表达式,它对应Java的switch语句,但它的语法和switch不同,它的selector 在match前面: 
selector match { alternatives}

一个模式匹配由多个可选项组成,没个选项由case开始,每个选项定义一个模式,每个模式对应一个表达式,表达式应用到当模式匹配的时候。模式和表达式之间使用=>分隔。 
一个match表达式的结果取决于第一个匹配的可选项,当该项模式匹配时,该模式=>后的表达式被选中然后计算该表达式的值。 
一个常量模式,比如本例中的“+”和“0”, 匹配对应的常数,一个变量模式比如e,可以匹配任意的值。然后=>右边的表示式可以应用这个变量,“_”为通配符,可以匹配任意的值。 
构造器模式,比如UnOp(“-”,e),可以匹配UnOp类型的值,这个UnOp的第一个参数为”-“,第二个参数可以为任意。

和Java的 switch语句比较,Scala的match 有以下几个不同点:

  • match为一表达式,有返回结果,其返回结果为匹配项表示式的值。
  • match的选项没有break,也不会自动匹配下一个选项(no fall through).
  • 如果没有一个选项匹配,那么将抛出MatchError异常,这意味着你必须保证考虑到Match的所有的选项,因此可能你需要添加一个缺省选项。
分享到:
评论

相关推荐

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

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

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

    Scala 语言中的 for 循环提供了强大的模式匹配功能,允许开发者在迭代过程中对数据进行模式匹配和过滤。本文将详细介绍 Scala 语言 for 循环中的六种模式匹配方式:变量模式匹配、常量模式匹配、变量绑定模式匹配、...

    4.样式类和模式匹配1

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

    大数据课程-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 _ => ...

    spark-db-case-class:将Spark DB名称映射到case类中的字段

    在Scala中,case类是常用于表示结构化数据的工具,它提供了便利的模式匹配和自动导出方法。`spark-db-case-class`项目就是针对这种情况,它旨在帮助我们将Spark数据库表的列名映射到Scala的case类字段,从而简化数据...

    Python-switchcase用纯Python实现的SwitchCase结构

    然而,它也有一些限制,比如无法像C++或Java那样在`case`中使用范围或字符串模式匹配。在更复杂的场景下,可能需要结合`if-elif-else`语句或者使用元类(metaclass)和装饰器(decorator)来实现更复杂的逻辑。 在...

    浅谈Scala模式匹配

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

    first-class-patterns:一流的模式和模式匹配,使用类型族

    总之,“first-class-patterns”项目探讨了如何在Haskell中扩展模式匹配的概念,使其更加强大和灵活。通过将模式提升为第一类公民,并结合类型族,我们可以构建更加复杂和动态的模式匹配系统,这对于处理数据解析、...

    Scala和设计模式.pdf

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

    Spark从入门到精通Java版

    Scala的模式匹配特点是,支持基本语法、对类型进⾏模式匹配、对Array和List的元素进⾏模式匹配、case class与模式匹配等。 类型参数 类型参数是一种编程技术,用于在编译时确定类型。Scala的类型参数特点是,支持...

    posmatch:自定义类的位置子模式匹配

    自定义类的位置子模式匹配。 要求 Python 3.8或更高版本。 注意:该程序包本身不需要Python 3.10,但是它的用法仅对Python 3.10中引入的新模式匹配功能有意义。 安装 pip install posmatch 用法 例子1 使用pos_...

    1、scala面试题(25问).pdf

    Scala面试题集锦 Scala是一种多-paradigm语言,集成...Scala语言是一种多-paradigm语言,集成了面向对象和函数式编程,具有闭包、柯里化、模式匹配、隐式转换等特点,对于程序员来说是一个非常有挑战性和有趣的语言。

    Scala考试题1

    - `unapply` 用于模式匹配,常在自定义的类型提取器中使用,如 `Some.apply()` 和 `Some.unapply()`。 6. **伴生对象和伴生类**: - 伴生对象与伴生类位于同一个源文件中,它们可以访问对方的私有成员。对象和类...

    scala的匹配样例类

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

    Scala样例类练习.docx

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

    C# 9 新特性的实际运用.docx

    模式匹配是C# 9中的一个重要增强,它允许我们在if语句、switch表达式或case子句中检查变量的类型或结构。这种特性可以更简洁地编写条件逻辑,提高代码可读性。例如,我们可以使用`is`关键字结合模式匹配来检查一个...

    数据类:具有更好二进制兼容性的案例类

    - **模式匹配**:在模式匹配表达式中,Case Class可以被解构为它的各个字段,大大简化了数据处理。 在压缩包`data-class-master`中,可能包含示例代码、测试用例或其他资源,这些可以帮助你更深入地理解和应用Case ...

    Scala语言规范.zip

    它还支持类、接口、特质(trait)等概念,以及模式匹配和高阶类型。 2. **函数式编程**:Scala鼓励使用不可变数据结构和纯函数,支持λ表达式(lambda)和柯里化(currying)。集合库是函数式编程的关键部分,提供...

    Scala编程详解 第21讲-Scala编程详解:Actor入门 共8页.pptx

    `case class`还支持模式匹配,使得Actor可以轻松地处理不同类型的消息。例如,创建一个处理用户注册和登录的`UserManageActor`: ```scala case class Login(username: String, password: String) case class ...

    scala程序设计2(中英文)

    6. **复合性管理**:Scala提供了一种名为“case class”的特殊类,用于创建具有模式匹配能力的数据结构。此外,还有case对象和模式匹配,用于简化复杂数据处理。 在"Programming.Scala.2nd.Edition.2014.12.pdf"和...

Global site tag (gtag.js) - Google Analytics