Scala 语法 Case Class和模式匹配

转载 2015年11月20日 09:36:06

本专题侧重介绍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

Case Class的特别之处在于: 编译器会为Case Class自动生成以下方法: equals & hashCode toString copy 编译器会为Case Class自动生成伴生对象...
  • bluishglc
  • bluishglc
  • 2016年03月17日 15:11
  • 14359

Scala Case Class介绍

Scala case class 介绍。
  • yyywyr
  • yyywyr
  • 2015年12月14日 21:24
  • 4336

scala 模式匹配与case class

当一个类被声明为case class时,编译器会自动进行如下操作: 1.构造器中参数如果没有被声明为var,则默认为val类型; 2.自动创建伴生对象,同时在伴生对象中实现apply方法,这样在使...
  • u013063153
  • u013063153
  • 2016年12月19日 16:19
  • 469

scala学习:模式匹配高级实战:嵌套的Case class

最近不清楚是工作忙的情况还是知识点越来越深入了。对知识的理解有点吃力起来。到目前已经好几章的视频都是模棱两可的。 先记录这节视频的内容吧。留待以后再深入理解吧。 示例代码: pa...
  • mzygssk
  • mzygssk
  • 2015年08月12日 22:47
  • 366

scala 的模式匹配与类型系统

主要内容: 1. scala模式匹配 2. scala类型系统
  • sinat_25306771
  • sinat_25306771
  • 2016年07月23日 15:10
  • 2737

Scala入门到精通——第十五节 Case Class与模式匹配(二)

本节主要内容 模式匹配的类型 for控制结构中的模式匹配 option类型模式匹配 1. 模式的类型1 常量模式object ConstantPattern{ def main(args: Arr...
  • lovehuangjiaju
  • lovehuangjiaju
  • 2015年08月01日 21:43
  • 11761

Spark学习笔记4-Scala模式匹配

1. 模式匹配Scala中的模式匹配用的关键字是match-case。类似java中的switch-case语句。 1.1 值的模式匹配代码如下: 定义一个函数bigData。对传入的参数做模式匹配...
  • xummgg
  • xummgg
  • 2016年01月26日 22:29
  • 1220

Scala语法 Case Class和模式匹配

本专题侧重介绍Scala的case class和pattern matching(模式匹配),这俩个两个程序结构对于处理树结构的数据非常有帮助。Scala的case class使得对对象进行模式匹配变...
  • wjacketcn
  • wjacketcn
  • 2015年11月20日 09:33
  • 400

scala之case class 和case object

-------------------- 1、case 类只用来修饰  class 和object,也就是说只有case class 和case object的存在 ,而没有case trait 这一...
  • legotime
  • legotime
  • 2016年08月26日 14:45
  • 1925

Scala之模式匹配(Patterns Matching)

前言首先,我们要在一开始强调一件很重要的事:Scala的模式匹配发生在但绝不仅限于发生在match case语句块中,这是Scala模式匹配之所以重要且有用的一个关键因素!我们会在文章的后半部分详细地...
  • bluishglc
  • bluishglc
  • 2016年04月04日 13:44
  • 8919
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Scala 语法 Case Class和模式匹配
举报原因:
原因补充:

(最多只允许输入30个字)