5、Scala模式匹配-创新互联

一、case class

创新互联建站专注于企业全网营销推广、网站重做改版、澧县网站定制设计、自适应品牌网站建设、成都h5网站建设电子商务商城网站建设、集团公司官网建设、成都外贸网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为澧县等各大城市提供网站开发制作服务。

    用case修饰的Class 我们称之为Case Class。编译器看到这个case修饰的class,会为这个class加一些额外的特性:

1、编译器会为Case Class增加一个以类名为名字的工厂方法,这个工厂方法作用是构建这个类的对象

                val v = Var("x") //构建对象的时候不需要用new关键词

2、编译器默认的为case class的值参数加上了val来进行修饰,所以这些值参数和一个类里的域一样

                v.name


3、编译器自动为case class添加了toString、hashCode以及equals方法。可以用 == 来比较case class,比较case class的类型以及case class中的值参数

op.right == Var("x")

4、编译器为case class增加了一个copy方法,使得case class的值参数的值可以修改。如果一个case class中只要几个特定的值参数需要改变的话,用copy比较方便。

              val opNew = op.copy(operator = "-")

    case 除了可以修饰class,还可以修饰object,就是表示一个单例对象

    case class大的优点就是配合模式匹配

二、Scala的match表达式 和java switch区别


    1、Scala的match表达式可以计算出一个值,而Java的switch却不能

    2、模式匹配的表达式永远不会穿透到下一个case表达式中, java的switch中没有break的话,则会穿透到下一个分支

    3、模式匹配中如果没有任何的模式被匹配到,则抛出MatchError异常


三、SealedClass

    当你在用模式匹配的时候,你肯定需要考虑所有场景的case,有的时候我们可以用default来代替所有没有考虑到的情况,但是有的时候这个默认值没有意义,这个时候怎么来保证你能考虑到所有的情况呢?我们让编译器来帮我们考虑,我们可以在case class的父类上加一个sealed的关键字,这个sealed会帮我们做两件事情:

      1:在我们定义模式匹配的时候,如果没有考虑全场景,编译器会报警告

        2:被sealed修饰的类,不能被在其他文件中的case class继承

四、模式的种类

    1、通配符模式 case _     可以用于匹配默认的场景,可以用于可以忽略的对象的域的情况

    2、常量模式


        def describe(x: Any) = x match {

              case 5 => "five"

              case true => "truth"

              case "hello" => "hi!"

              case Nil => "the empty list"

              case _ => "something else"

             }

              describe(5) //res6: String = five

              describe(true) //res7: String = truth

              describe("hello") //res8: String = hi!

              describe(Nil) //res9: String = the empty list

              describe(List(1, 2, 3)) //res10: String = something else

    3、变量模式

            可以将被匹配的表达式的值绑定到模式中的变量中,这样可以在expressions中使用这个变量

              val i = 1 + 1

              var result = i match {

               case 0 => "zero"

               case somethingElse => "not zero: " + somethingElse

              }

              println(result) // not zero: 2

            编译器怎么判断是常量模式还是变量模式?

              val pi = math.Pi

              result = E match {

               case pi => "strange math? Pi = " + pi //以小写字母开头的单词被编译器认为是变量模式

              }

              result = E match {

               case `pi` => "strange math? Pi = " + pi //以反引号扩起来的为常量模式

               case _ => "OK"

              }

    4、构造器模式。支持深度匹配

    5、序列模式。支持固定长度的序列或者数组,也支持非固定长度。


                v match {

                   case List(0, _*) => println("list it")//匹配含有任意个元素的List,并且第一个元素等于0

                   case Array(0, _*) => println("array it")//匹配含有任意个元素的Array,并且第一个元素等于0

                   case _ =>

                  }

    6、元组模式

             def tupleDemo(expr: Any) = expr match {

              case (a, b, c) => println("matched " + a + b + c)

              case _ =>

             }

7、类型模式

        def generalSizeWithPattern(x: Any) = x match {

           case s: String => s.length

           case m: Map[Int, Int] => m.size

           case _ => -1

          }

        关于类型擦除,数组是个例外,因为数组在java中是特殊处理了,在scala中也是特殊处理了,在jvm中对应着不同类型的数组,比如int[], float[]等

          isIntIntMap(Map(1 -> 1)) //true

          isIntIntMap(Map("abc" -> "abc")) //true


          isStringArray(Array("abc")) //yes

          isStringArray(Array(1, 2, 3)) //no

8、变量绑定

      val expr = UnOp("abs", UnOp("abs", Var("x")))

      expr match {

       case UnOp("abs", e@UnOp("abs", i@Var(_))) => println(e + " " + i)

       case _ =>

      }

五、模式守卫

  在模式中可以定义条件。

    def simplifyAdd(e: Expr) = e match {

  case BinOp("+", a, b) if a == b => BinOp("*", b, Number(2))

  case _ => e

  }

六、模式重叠


尽量避免模式重叠

    def simplifyBad(expr: Expr): Expr = expr match {

      case UnOp("-", UnOp("-", e)) => e  //第一个case

      case UnOp(op, e) => UnOp(op, simplifyBad(e)) //第二个case

     }

    当case1属于case2的子集,那么case1可以放在case2之前,若放在case2之后,则永远无法执行,编译器会报警告unreachable code.


七、Option

    Option视作一个容器,可以有东西,也可以没有东西。Some 表示有且仅有一个东西 None表示没有东西


    val opt = Some("aaa")


    opt.getOrElse("default")



     在模式匹配中使用:

    val capitals =

       Map("France" -> "Paris", "Japan" -> "Tokyo")

    def show(x: Option[String]) = x match {

      case Some(s) => s

      case None => "?"

     }

    show(capitals get "Japan") //res25: String = Tokyo

    show(capitals get "France") //res26: String = Paris

    show(capitals get "North Pole") //res27: String = ?

八、模式在变量定义中的使用

  val myTuple = (123, "abc")

  val (number, string) = myTuple

  val exp = new BinOp("*", Number(5), Number(1))

  val BinOp(op, left, right) = exp

九、模式在偏函数中使用

    1、一个case序列作为全函数(complete function)

      val withDefault: Option[Int] => Int = {

       case Some(x) => x

       case None => 0

      }

    2、如果缺少了一个case会出现什么情况呢?编译会出现警告

      val second: Option[Int] => Int = {

       case Some(x) => x

      }

     3、如果我们的case列表是部分的场景,我们需要告诉编译器这是一个偏函数(partial function)

      val partial : PartialFunction[Option[Int], Int] = {

       case Some(x) => x

      }

    4、我们尽可能的用全函数,因为偏函数如果没有考虑清楚需要处理的case的话,可能会抛异常。

    上面的partial就是和下面的p是一个意思

       val p = new PartialFunction[Option[Int], Int] {

       override def isDefinedAt(x: Option[Int]) = x match {

        case Some(_) => true

        case None => false

       }


       override def apply(v1: Option[Int]) = v1 match {

        case Some(x) => x

       }


    5、如果要使用偏函数,推荐用下面模式

      if (partial.isDefinedAt(None)) {

       partial(None) //如果单独运行的话,还是会抛异常

      }

十、模式在for中使用

  val results = List(Some("apple"), None, Some("orange"))

  for (Some(fruit) <- results) println(fruit)

  val capitals =

   Map("France" -> "Paris", "Japan" -> "Tokyo")

  for ((country, city) <- capitals)

   println("The capital of " + country + " is " + city)

十一、萃取器unapply


    含有成员方法unapply的object,我们称之为extractors(萃取器)。extractors可以同时定义apply(可选的)和unapply方法。


另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


新闻名称:5、Scala模式匹配-创新互联
网页URL:http://ybzwz.com/article/cccdsd.html