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

//样本类case class
//层级包括一个抽象基类Expr和四个子类,每个代表一种表达式
//样本类自动添加与类名一致的工厂方法
abstract class Expr
case class Var(name:String) extends Expr//括号内参数不用加val,默认为加val的字段
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
  def main(args:Array[String]):Unit = {
//1、样本类自动添加与类名一致的工厂方法,所以可以不用new就构造出相应对象
val v = Var("x");
val op = BinOp("+",Number(1.0),v);
//2、样本类参数列表中的所有参数隐式获得了val前缀,构造器中的每一个参数都成为val,除非显式生命为var(不建议)
var s1:String = v.name
//3、此外将生成toString equals hashCode copy方法,除非显式定义
//除上述外,样例类与其他类完全一样
//============================================================//  
//match对应于Java里的Switch
//选择器 match{备选项} 取代了 switch{选择器}{备选项}
//一个备选项包含了一个模式以及多个表达式,箭头符号=>隔开了模式与表达式 //本函数不对表达式进行任何的改变,只用来返回用来做匹配的表达式expr
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 //如果没有通配, 在匹配不到的时候抛出异常    
    }
println(simplifyTop(BinOp("+",v,Number(0))))
println(simplifyTop(BinOp("*",op,Number(1))))
}

模式匹配

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

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

模式的种类

  通配模式 

    通配模式_匹配任意对象,也可以用来忽略对象中不关心的部分

  常量模式

    常量模式仅仅匹配自身。任何字面量都可以作为常量

  变量模式

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

  def pipei (x:Any) = {
x match{
case 0 => "zero"  //常量模式
case somethingElse => "not zero" + somethingElse  //变量模式
}
}

  构造器模式

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

  序列模式

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

    val myList = List(1,1,2,3)
def findL(l1:List[Int]):Unit={
l1 match{
case List(0,1,_,_) =>println("找到了!");
case _ =>println("没找到!");
}
}
findL(myList)

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

  元组模式

 def tupleDemo(expr : Any) = 
expr match {
case (a , b, c) => println("matched " + a + b + c)
case _ =>
}

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

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

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

      res15 : Int = 2

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

  模式守卫

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

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

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

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

  类型擦除:

def isIntMap(x:Any)={
x match{
case m: Map[Int,Int]=>true
case _ =>false
}
}
val m1 =Map(1->11,2->22)
val m2 = Map("s1"->"sss111")
println(isIntMap(m1))
println(isIntMap(m2))
打印出  true
     true

第一个true看起来正确,第二个true看起来不合理,因为只能判断出是某种参数类型的Map,而不能判断出参数类型

擦除规则的唯一例外就是数组。

//数组的类型,不擦除
def isStringArray(x:Any)={
x match{
case s:Array[String]=>true
case _=> false
}
}
val a1 = Array("aa","bb")
val a2 = Array[Int](1,2)
println(isStringArray(a1))
println(isStringArray(a2))

打印出   true

    false

  变量绑定

如果匹配成功,把变量设置成匹配的对象

    //变量绑定
def doubleABS(expr:Expr)={
expr match{
case UnOp("abs",e @ UnOp("abs",_))=>e //相当于把UnOp("abs",_)绑定到e,以便后面使用
case _ =>
}
}
val e1 = UnOp("abs",UnOp("abs",v))
println(doubleABS(e1))

输出:UnOp(abs,Var(x))

模式守卫

模式守卫开始于if 只有在守卫返回true时匹配才成功。

//模式守卫
def simplifyAdd(expr:Expr)={
expr match{
//case BinOp("+",x,x)=>BinOp("*",x,Number(2))错误,不能有两个x,模式变量仅允许在模式中出现一次
case BinOp("+",x,y) if(x==y )=>BinOp("*",x,Number(2))
case _=>expr
}
}

封闭类

sealed abstract class Expr //加上sealed 代表封闭类
case class Var(name:String) extends Expr//括号内参数不用加val,默认为加val的字段
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
//封闭类除了类定义所在的文件之外,不能再添加任何新的子类。
//如果使用继承自封闭类的样本类做匹配,若缺失了某种模式组合,编译器将警告
//封闭类的使用
def fengbi(expr:Expr)={
expr match{ //有警告标志,因为丢失了可能样本的模式匹配
case BinOp("+",e,y)=>e;
}
}

编译后的警告

Description Resource Path Location Type
match may not be exhaustive.

It would fail on the following inputs:

BinOp((x: String forSome x not in "+"), _, _), Expr(), Number(_), UnOp(_, _), Var(_)

Test1.scala /test14/src/com/evor/test14 line 93 Scala Problem

Option类型

def main(args:Array[String]):Unit = {
val captials = Map("China"->"Beijing","France"->"Paris")
val c = captials.get("China") //get方法返回可选值,Map的get方法在找到指定键时返回Some(value),否则返回None
val a = captials.get("Americas")
println(c)
println(a) def show(x:Option[String])={ //通过模式匹配,分离可选值
x match{
case Some(s)=>s
case None=> "Don't know." //如果可选类型为None 返回don't know
}
}
println(show(c))
println(show(a))
}

运行结果:

Some(Beijing)
None
Beijing
Don't know.

Scala学习文档-样本类与模式匹配(match,case,Option)的更多相关文章

  1. Scala学习文档-列表的使用

    注:列表是不可变的,不能通过赋值改变列表的元素 列表具有递归结构,数组是连续的 scala里的列表类型是协变的?  --> scala中的逆变与协变 分治原则 //自定义实现:::操作符 def ...

  2. Scala学习文档-各种使用模式的情况

    模式在变量定义中 在定义val或者var的时候,可以使用模式替代简单的标识符,如可以使用模式拆分元组,并把每个值分配给变量 val myTuple = (123,"abc") va ...

  3. Scala学习文档-访问修饰符

    在scala里,对保护成员的访问比Java严格.Scala中,保护成员只在定义了成员的类的子类中可以访问,而Java中,还允许在同一个包的其他类中访问. package p1 { class FCla ...

  4. scala学习笔记(四)样本类与模式匹配

    访问修饰符 格式:private[x]或protected[x],x指某个所属包.类或单例对象,表示被修饰的类(或方法.单例对象),在X域中公开,在x域范围内都可以访问: private[包名]:在该 ...

  5. 2013 最新的 play web framework 版本 1.2.3 框架学习文档整理

    Play framework框架学习文档 Play framework框架学习文档 1 一.什么是Playframework 3 二.playframework框架的优点 4 三.Play Frame ...

  6. soapUI学习文档(转载)

    soapUI 学习文档不是前言的前言记得一个搞开发的同事突然跑来叫能不能做个WebService 性能测试,当时我就凌乱了,不淡定啊,因为我是做测试的,以前连WebService 是什么不知道,毕竟咱 ...

  7. Spark样本类与模式匹配

    一.前言 样本类(case class)与模式匹配(pattern matching)是Scala中一个比较复杂的概念,往往让人感觉深陷泥沼.我在这里对Scala中的样本类与模式匹配进行了一些整理,希 ...

  8. Ext JS 6学习文档-第8章-主题和响应式设计

    Ext JS 6学习文档-第8章-主题和响应式设计 主题和响应式设计 本章重点在 ExtJS 应用的主题和响应式设计.主要有以下几点内容: SASS 介绍和入门 主题 响应式设计 SASS 介绍和入门 ...

  9. Ext JS 6学习文档-第6章-高级组件

    Ext JS 6学习文档-第6章-高级组件 高级组件 本章涵盖了高级组件,比如 tree 和 data view.它将为读者呈现一个示例项目为 图片浏览器,它使用 tree 和 data view 组 ...

随机推荐

  1. css 动画 transform transition animation

    1.transform  transform 是通过在浏览器里面让网页元素 移动 旋转 透明 模糊 等方法来实现改变其外观的技术 -webkit-transform : translate(3em,0 ...

  2. 使用jquery 操作checkbox

    checkbox 的全选与全不选以及获取选择的值. 效果: <!DOCTYPE html> <html lang="en"> <head> &l ...

  3. ServletConfig对象 【通过此对象获取到web.xml中的信息】

    用途:       1)想让当前的Servlet读取一些在web.xml文件配置的初始化参数时,                      可以使用ServletConfig对象,他是Servlet运 ...

  4. Teach Yourself Scheme in Fixnum Days 13 Jump跳转

    Jumps One of the signal features of Scheme is its support for jumps or nonlocal control. Specificall ...

  5. jQuery自定义函数验证邮箱格式

    jQuery.fn.checkEmail = function() { // 自定义jQuery方法 var email_val = $(this).val(); reg = /^\w+([-+.]\ ...

  6. c语言验证哥德巴赫猜想(从4开始 一个偶数由两个质数之和)

    #include <stdio.h> #include <stdlib.h> #include <math.h> int isit(int num) { int i ...

  7. hdu 5410 CRB and His Birthday(混合背包)

    Problem Description Today is CRB's birthday. His mom decided to buy many presents for her lovely son ...

  8. iOS 提示音播放

    首先找到对应的素材 音频文件 写一个类继承 NSObject 命名为AudioUtil 导入支撑文件 #import <AVFoundation/AVFoundation.h> #impo ...

  9. Open Session In View

    Open Session In View模式的主要思想是:在用户的每一次请求过程始终保持一个Session对象打开着 实现步骤: 步骤一.创建一个Web项目,创建包cn.happy.util,创建Hi ...

  10. CSS3 div水平、垂直居中,IE9以上、Firefox、Chrome均正常

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...