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


    访问修饰符

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

    private[包名]:在该包名作用域内,被修饰域都能被访问;

    private[类名]:在该类的作用域,被修饰域都能被访问;

    private[this]:仅能在包含了定义的同一对象中访问,用于保证同一类中不能被其它对象访问;

    例子:

    package tests{
        private[tests] class Test{
            private[tests] def showTest=println("start showTest Runing !")
        }
        package units{
            object unit{
                def main(args:Array[String]){
                    val a = new Test
                    a.showTest
                }
            }
        }
    }

     

    样本类

    定义:带有case修饰符的类称为样本类(case class);

    例如:

    case class Unit(name:String)

    val t = Unit(“123)

    scala为样本类提供的便捷特点:

    1、添加了与类名相同的工厂方法,也就是说可以用Unit(“123”)替换new Unit(“123”)构造对象;

    2、样本类参数列表中的所有参数隐式获得了val前缀,被当作字段维护,如:t.name;

    3、编译器为类添加了方法toString、hashCode和equals的实现;

     

    模式匹配

    一个模式匹配包含了一系列备选项,以case关键字开始,每个备选项都包含了一个模式及一到多个表达式,他们在模式匹配过程中被计算,箭头符号=>隔开了模式和表达式;

    格式:选择器 match {备选项}

    备选项格式:case 模式 => 表达式

    match与switch比较:

    1、match 是scala表达式,始终以值做为结果;

    2、备选项永远不会掉到下一个case执行;

    3、如果没有模式匹配到,将抛出MatchError异常;

     

    模式的种类

    通配模式:能匹配任意对象,如:case _ => todo

    常量模式:任何字面量、val、单例对象(Nil)都可以做为常量,仅能匹配自身,如:def fun(x:Any) = x match {case Nil => “123”;case _ => “456”};

    变量模式:类似通配符,可以匹配任意对象,与通配模式不同的是,它会把变量绑定在匹配的对象上,因此之后可以使用这个变量操作对象;

    如:

    scala> var p = "123456"
    p: String = 123456

    scala> def fun(x:Any) = x match {
         | case p => println("fun result is :"+p)
         | }
    fun: (x: Any)Unit

    scala> fun("hello world")
    fun result is :hello world

    说明:

    1、scala中小写字母开始的简单名被当作是模式变量,所有其它的引用被认为是常量。

    2、以反引号包住变量名表示是常量;

     

    构造器模式

    假如模式指定为一个样本类,那么这个模式就表示首先检查对象是该名称的样本类成员,然后检查对象的构造参数是否符号额外提供的模式,该模式使scala支持深度匹配;

    例子:

    scala> case class Unit(x:String){
         | def showUnit=println("showUnit " + x);
         | }
    defined class Unit 
                     
    scala> def fun(x:Any) = x match {
         | case Unit("123") => println("123456")
         | case _ => println("no match")
         | }
    fun: (x: Any)Unit

    scala> fun(new Unit("234"))
    no match

    scala> fun (new Unit("123"))
    123456

     

    序列模式

    匹配List或Array这样的序列类型,同样的语法也可以指定模式内任意数量的元素;

    如:

    scala> def fun (x:Any)= x match{
         | case List(0,_,_) => println("123")
         | case _ => println("no match")
         | }
    fun: (x: Any)Unit

    scala> fun(List(1,2,3))
    no match

    说明:匹配一个不指定长度的序列可以 _*做为模式的最后元素,如:List(0,_*);

     

    元组模式

    用于匹配元素,类似(a,b,c)这样的模式可以匹配任意的三元组;

    如:

    scala> def fun(x:Any) = x match {
         | case ("123",1,2) => println("123")
         | case _ => println("no match")
         | }
    fun: (x: Any)Unit

    scala> fun((1,2,3))
    no match

    scala> fun(("123",1,2))
    123

     

    类型模式

    可把类型模式当作类型测试和类型转化的简易替代;

    如:

    scala> def fun(x:Any) = x match {
         | case s:String => println("String Type length is" + s.length)
         | case _ => println("no match")
         | }
    fun: (x: Any)Unit

    scala> fun("123456")
    String Type length is6

    说明:

    1、与该模式功能相同的还有两个函数 isInstanceof(类型测试)与 asInstanceof(类型转换)

    2、x.isInstanceof[String]检查x是否为String类型类型,是就返回true否则返回false;

    3、x.asInstanceof[String]将x转换为String类型返回;

    4、类型擦除:类型参数信息没有保留到运行期,因此,运行期没有办法判定给定的Map对象创建时带了两个Int参数还是其它的类型,,系统只能判定这个值是某种任意类型参数的Map,而唯一例外的数组类型Array[类型];

     

    变量绑定模式

    除了独立的变量模式外,可使用该模式对任何其它模式添加变量,格式:变量名+@+模式,这种模式的意义在于它能像通常的那要做模式匹配,并且如果匹配成功,则把变量设置成匹配的对象;

    例子:

    scala> case class Unit(a:Int,b:String){
         | def showUnit=println("a:"+a+",b:"+b)
         | }
    defined class Unit

    scala> def fun(x:Any)= x match {
         | case Unit(1,e @ "123") => println("e:"+e)
         |  case _ => println("No Match")
         | }
    fun: (x: Any)Unit

    scala> fun(Unit(1,"123"))
    e:123

    scala> fun(Unit(1,"234"))
    No Match

     

    模式守卫

    scala要求模式是线性的:模式变量仅允许在模式中出现一次,不过可以使用模式守卫重新指定该匹配规则;

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

    例子:

    scala> def fun(x:Any)=x match {
         | case i:Int if i>0 => println("i>0")
         | case s:String if s.length ==3 => println("type is String")
         | case _ => println("No Match")
         | }
    fun: (x: Any)Unit

    scala> fun(123)
    i>0

    scala> fun("123")
    type is String

    scala> fun(-1)
    No Match

     

    模式重叠

    模式以代码编写的先后次序尝试执行,很重要的一点是,全匹配的样本要跟在具体的简化方法之后,如果写成其它次序,那么全匹配样本将比特定规则样本得到更高的优先级,这种情况下,编译器将在你做这种尝试时发出警告,因为特定规则的样本没有可能执行;

     

    封闭类

    功能:scala编译器帮助检查match表达式中遗漏的模式组合。

    原理:让样本类的超类被封闭,封闭类除了类定义所在的文件外不能再添加任何新的子类,而仅需要关系所定义的子类。当使用封闭类的样本类进行模式比配时,编译器会自动检查是否存在缺失的模式组合,存在时将抛出警告;

    例子:

    scala> sealed abstract class Unit
    defined class Unit

    scala> case class U1(s:String) extends Unit
    defined class U1

    scala> case class U2(i:Int) extends Unit
    defined class U2

    scala> case class U3(b:Any) extends Unit
    defined class U3

    scala> def fun(x:Unit) = x match {
         | case U1(_) => println("U1")
         | case U2(_) => println("U2")
         | }
    <console>:12: warning: match may not be exhaustive.
    It would fail on the following input: U3(_)

    使用注解去掉警告:

    scala>  def fun(x:Unit) = (x: @unchecked) match {
         |  case U1(_) => println("U1")
         | case U2(_) => println("U2")
         | }
    fun: (x: Unit)Unit

    说明:

    模式匹配的类层级,都应当使用封闭类,而封闭类的实现把关键字sealed放在最顶层类的前面即可;

     

    Option类型

    该类型为一种可选值的定义,有两种形式Some(x),其中x为实际值和None,代表缺省值。可作用于scala集合类的某些标准操作会产生可选值;

    例子:

    scala> val ss = Map("123"->"Hello","456"->"World")
    ss: scala.collection.immutable.Map[String,String] = Map(123 -> Hello, 456 -> Wor
    ld)

    scala> def fun(x:Option[String])= x match {
         | case Some(s) => println(s)
         | case None => println("No Match")
         | }
    fun: (x: Option[String])Unit

    scala> fun(ss get "123")
    Hello

    scala> fun(ss get "567")
    No Match

    注意:Option[String]与String两种是不同的类型,不能互相赋值;

     

    模式的应用

    1、变量的定义

    例1:

    scala> val aa = (123,"456")
    aa: (Int, String) = (123,456)

    scala> val (a,b) = aa
    a: Int = 123
    b: String = 456

    scala> println(a)
    123

    scala> print(b)
    456

     

    2、偏函数的样本序列

    样本序列就是函数字面量,与通常的函数里子面量不同的是,样本序列可以有多个入口点,每个都有自己的参数列表,每个样本都是函数的一个入口点,参数被模式特化。而通常的函数字面量只有一个入口;

    例1(样本序列):

    scala> val fun:Option[Int] => Int ={
         | case Some(x) => x
         | case None => 0
         | }
    fun: Option[Int] => Int = <function1>

    scala> fun(Some(10))
    res2: Int = 10

    scala> fun(None)
    res3: Int = 0

    例2(偏函数应用):

    scala> val fun:PartialFunction[List[Int],Int] = {
         | case x :: y :: _ => y
         | }
    fun: PartialFunction[List[Int],Int] = <function1>

    scala> fun.isDefinedAt(List(5,6,7))
    res6: Boolean = true

    scala> fun.isDefinedAt(List(2))
    res7: Boolean = false

    说明:

    1、PartialFunction[List[Int],Int]表示仅包含从整数列表到整数的偏函数;

    2、fun.isDefinedAt用于检查该偏函数对List(5,6,7)有定义,上例中表示函数对任何有至少两个元素的列表有定义;

  • 相关阅读:
    Spring sprint @ ninth day
    微软面试:找水王问题
    Spring sprint @ first day
    软件工程概论 购书最低价格问题
    网络助手的NABCD分析
    记初学net-SNMP
    求二维数组联通子数组和的最大值 (联通涂色) beta!
    二维数组环状最大子矩阵
    一维数组中的最大子数组(环状)
    图书助手冲刺第七天
  • 原文地址:https://www.cnblogs.com/jianyuan/p/4351993.html
Copyright © 2020-2023  润新知