scala模式匹配与样例类

样本类:添加了case的类便是样本类。这种修饰符可以让Scala编译器自动为这个类添加一些语法上的便捷设定。如下:

1.添加与类名一致的工厂方法。也就是说,可以写成Var("x")来构造Var对象。
    2.样本类参数列表中的所有参数隐式获得了val前缀,因此它被当作字段维护。

3.编译器为这个类添加了方法toString,hashCode和equals等方法。

模式匹配:

match对应Java里的switch,但是写在选择器表达式之后。即: 选择器 match {备选项}。

  一个模式匹配包含了一系列备选项,每个都开始于关键字case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。

  match表达式通过以代码编写的先后次序尝试每个模式来完成计算。类似于UnOp("-" , UnOp("-" , e))这种形式的,是构造器模式匹配。

  match与switch的比较:匹配表达式可以被看作Java风格Switch的泛化。但有三点不同:

  1. match是Scala的表达式,始终以值作为结果;
  2. Scala的备选项表达式永远不会“掉到”下一个case;
  3. 如果没有模式匹配,MatchError异常会被抛出。这意味着必须始终确信所有的情况都考虑到了,或者至少添加一个默认情况什么都不做。如 case _ =>

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

代码示例:

[java] view plain copy

print?

  1. /*
  2. desc:模拟控制数学表达式的库。
  3. 由变量、数字、一元及二元操作符组成的数学表达式。
  4. jb,完全照书上的来说。
  5. */
  6. object simpleBegin {
  7. def main(args: Array[String]): Unit = {
  8. //--x
  9. println(simplifyTop(UnOp("-", UnOp("-", Var("x")))))
  10. //x+0
  11. println(simplifyTop(BinOp("+", Var("x"), Number(0))))
  12. //x*1
  13. println(simplifyTop(BinOp("*", Var("x"), Number(1))))
  14. //abs abs x
  15. println(simplifyTop(UnOp("abs", UnOp("abs", Var("x")))))
  16. }
  17. //层级包括一个抽象基类Expr和四个子类,每个代表一种表达式。所有的五个类都没有结构体。
  18. //class C 和 class C {} 一个意思。
  19. abstract class Expr
  20. case class Var(name: String) extends Expr
  21. case class Number(num: Double) extends Expr
  22. case class UnOp(operator: String, arg: Expr) extends Expr
  23. case class BinOp(operator: String, left: Expr, right: Expr) extends Expr
  24. //“e“是什么意思????变量模式!
  25. //tips: case BinOp("*", e, Number(1)) => e 可以写成: case BinOp(a, e, b) => e !!!!!!!!!!!!!
  26. def simplifyTop(expr: Expr): Expr = expr match{
  27. case UnOp("-", UnOp("-", e)) => e
  28. case BinOp("+", e, Number(0)) => e
  29. case BinOp("*", e, Number(1)) => e
  30. //变量绑定,规则:变量 @ 模式,此时“变量”就代表了后面的“模式”:Unop("abs", _)
  31. case UnOp("abs", x @ UnOp("abs", _)) => x
  32. }
  33. }

-------------------------------------------------------------------------------------------------------------------------------------------------------------

输出结果:

Var(x)
Var(x)
Var(x)
UnOp(abs,Var(x))

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

模式的种类

通配模式:case _ => 。表示默认的全匹配备选项。通配模式还可以用来忽略对象中不关心的部分。如:case BinOp(_,_,_) => XXX,则表示不关心二元操作符的元素是什么,只是检查是否为二元操作符

常量模式 :仅匹配自身。任何字面量都可以用作常量。包括String类型。另外,任何的val或单例对象也可以被用作常量。如,单例对象Nil是只匹配空列表的模式。

变量模式 :变量模式类似于通配符,可以匹配任何对象。不同点在于,Scala把变量绑定在匹配的对象上。之后就可以使用这个变量操作对象。如:

[java] view plain copy

print?

  1. expr match{
  2. case 0 => "zero"
  3. case somethingElse => "not zero" + somethingElse
  4. }       

*有一个注意点:Scala使用了一个简单的文字规则来区分是一个常量还是一个变量:用小写字母开始的简单名被当作是模式变量。

构造器模式:它的存在使得模式匹配真正变得强大。它由名称及若干括号之内的模式构成。如BinOp("+" , e , Number(0))。

序列模式:可以像匹配样本类那样匹配List或Array这样的序列类型。同样的语法现在可以指定模式内任意数量的元素。如:

[java] view plain copy

print?

  1. expr match{
  2. case List(0 , _ , _ ) => println("found it")
  3. case _ =>
  4. }

如果想匹配一个不指定长度的序列,可以指定_*作为模式的最后元素。它能匹配序列中0到任意数量的元素。

元组模式:例子:

[java] view plain copy

print?

  1. def tupleDemo(expr : Any) =
  2. expr match {
  3. case (a , b, c) => println("matched " + a + b + c)
  4. case _ =>
  5. }

 

类型模式:可以把它当做类型测试和类型转换的简易替代。例如:

[java] view plain copy

print?

  1. def generalSize(x : Any) = x match{
  2. case s : String => s.length
  3. case m : Map[_ , _] => m.size
  4. case _ => 1
  5. }

使用: scala> generalSize(Map(1 -> ‘a‘ , 2 -> ‘b‘))

    res15 : Int = 2

另:在Scala里类型测试和转换的代码很冗长,因为不建议这么做。

[java] view plain copy

print?

  1. case BinOp("+" , x , x ) => BinOp("*" , x , Number(2))

 

模式守卫:模式变量仅允许在模式中出现一次。如:

  这种写法就会出错。可以改成:  case BinOp("+" , x , y ) if x == y => BinOp("*" , x , Number(2))

  模式守卫接在模式之后,开始于if。守卫可以是任意的引用模式中变量的布尔表达式。如果存在模式守卫,那么只有在守卫返回true的时候匹配才成功。

时间: 2024-10-23 14:50:17

scala模式匹配与样例类的相关文章

好程序员大数据教程分享Scala系列之模式匹配和样例类

好程序员大数据教程分享Scala系列之模式匹配和样例类1.样例类在Scala中样例类是一中特殊的类,样例类是不可变的,可以通过值进行比较,可用于模式匹配.定义一个样例类:1.构造器中每一个参数都是val,除非显示地声明为var 2.伴生对象提供apply ,让你不使用new关键字就能构造出相应的对象case class Point(x: Int, y: Int)创建样例类对象:val point = Point(1, 2)val anotherPoint = Point(1, 2)val yet

从零学scala(七)集合、模式匹配和样例类

一:集合 主要的集合特质 scala集合中重要的特质: Trait(Iterable) Trait(Seq) Trait(Set) Trait(Map) Trait(IndexedSeq) Trait(SoredSet) Trait(SoredMap) Seq是一个有先后次序的值的序列,比如数组和列表.IndexSeq允许我们通过下表快速访问元素,ArrayBuffer是带下标的,但是链表不是. Set是一个没有先后次序的值的序列,SortedSet中,元素以排过序的顺序被访问. Map是一组(

好程序员大数据教程Scala系列之样例类_Option_偏函数

好程序员大数据教程Scala系列之样例类_Option_偏函数,在Scala中Option类型样例类用来表示可能存在或也可能不存在的值(Option的子类有Some和None).Some包装了某个值,None表示没有值. object?OptionDemo {??def?main(args: Array[String]) {????val?map = Map("a"?-> 1, "b"?-> 2)????val?v = map.get("b&q

模式匹配和样例类

模式匹配是类似switch-case特性,但更加灵活:也类似if-else,但更加简约. 1 def fibonacci(i : Any) : Int = i match { 2 case 0 => 0 3 case 1 => 1 4 case n : Int if (n > 1) => fibonacci(n -1) + fibonacci(n - 2) 5 case _ => 0 6 } 7 8 println(fibonacci(3)) 9 println(fibona

【转】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 1 2 3 4 5 6 7 8 va

快学Scala第14章----模式匹配和样例类

本章要点 match表达式是一个更好的switch,不会有意外掉入到下一个分支的问题. 如果没有模式能够匹配,会抛出MatchError.可以用case _ 模式来避免. 模式可以包含一个随意定义的条件,称作守卫. 你可以对表达式的类型进行匹配:优先选择模式匹配而不是isInstanceOf/asInstanceOf. 你可以匹配数组.元组和样例类的模式,然后将匹配到的不同部分绑定到变量. 在for表达式中,不能匹配的情况会被安静的跳过. 样例类继承层级中的公共超类应该是sealed的. 用Op

【Scala篇】--Scala中Trait、模式匹配、样例类、Actor模型

一.前述 Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大. 模式匹配机制相当于java中的switch-case. 使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类. Actor相当于Java中的多线程. 二.具体阐述 trait特性 1.概念理解 Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大. 与接口不同的是,它还可以定义属性和方法的实现. 一般情况下Scala的类可以继承多个Tra

Scala笔记整理(七):模式匹配和样例类

[TOC] 可以用到switch语句 1.Scala强大的模式匹配机制,可以应用在switch语句.类型检查以及"析构"等场合. def swithOps: Unit ={ var sign = 0 val ch: Char = '+' ch match { case '+' => sign = 1 case '-' => sign = -1 case _ => sign = 0 } println("sign===> " + sign) }

快学Scala(14)--模式匹配和样例类

更好的switch def main(args: Array[String]): Unit = { var sign: Int = 0 val ch: Char = '+' val color = Color.BLACK sign = ch match { case '+' => 1 case '-' => -1 case _ => 0 } color match { case Color.RED => ; case Color.BLACK => ; case _ =>