Scala中Case Class與匹配模式是怎麼回事

一.匹配模式

Scala中匹配模式,類似與Java中的Switch。不過,Scala中匹配模式避免了Java Switch忘記Break時,穿透的問題。

演示如下:

  

  for(i <- 1 to 100){
      i match{
        case 10 => println(10)
        case 50 => println(50)
        case 100 => println(100)
        //增加條件
        case _ if(i % 4 == 0) => println(i + ":能被4整除")
        case _ if(i % 3 == 0) => println(i + ":能被3整除")
        case _ =>
      }
    }

二.Case Class

1. Case Class使用

   

 object caseTest {
      def main(args: Array[String]): Unit = {
        val p:Person = Student("Tom",22,80)
        p match{
          case Student(name,age,sno) => println("this is a student!")
          case Teacher(name,age,tno) => println("this is a teacher!")
          case Nobody(name) => println("unknown:"+name)
        }
      }
    }
    abstract class Person
    case class Student(name:String,age:Int,sno:Int) extends Person
    case class Teacher(name:String,age:Int,tno:Int) extends Person
    case class Nobody(name:String) extends Person

Case Class總結

    構造器的參數如果不被聲明爲var,默認是val
    自動創建伴生對象同時實現apply方法,使得我們不必須new對象
    伴生對象中同樣實現unapply方法,將case class應用於模式匹配
    實現自己的toString、hashCode、copy、equals方法
    除此之外,與普通class沒有區別

2.Case Class常用方法

    object caseTest {
      def main(args: Array[String]): Unit = {
        val t = Teacher("James",34,1)
        //無參copy方法
        val t1 = t.copy()
        println(t eq t1) //比較引用,false;深度拷貝
        println(t == t1) //比較內容,true
        println(t.equals(t1)) //比較內容,true
        //帶一個參數的copy方法
        println(t1.copy(name = "Kobe"))
        //帶二個參數的copy方法
        println(t1.copy(name = "Kobe",age = 22))
        //帶三個參數的copy方法
        println(t1.copy(name = "Kobe",age = 22,tno = 2))
        //hashCode方法
        println(t1.hashCode())
        //toString方法
        println(t1.toString())
      }
    }
    abstract class Person
    case class Student(name:String,age:Int,sno:Int) extends Person
    case class Teacher(name:String,age:Int,tno:Int) extends Person
    case class Nobody(name:String) extends Person

3.多參數Case Class

    object caseTest {
      def main(args: Array[String]): Unit = {
        val sc = School("好好學習!",Teacher("Jordan",40,1),Student("Kobe",22,2))
        sc match{
          case School(_,_,Student(name,age,sno)) => println(name)
          case _ => println("Nobody")
        }
      }
    }
    abstract class Person
    case class Student(name:String,age:Int,sno:Int) extends Person
    case class Teacher(name:String,age:Int,tno:Int) extends Person
    case class Nobody(name:String) extends Person
    //School爲接受多個Person類型參數的類
    case class School(desc:String,persons:Person*)

4.sealed case class

有時候進行模式匹配,需要確保所有可能情況都列出,此時常常將它的超類定義爲sealed(密封的)case class。

    object caseTest {
      def main(args: Array[String]): Unit = {
        
        val s:Person = Student("Lily",19,3)
        //編譯器會提示:只匹配到了Student
        //match may not be exhaustive.
        //It would fail on the following inputs: Nobody(_), Teacher(_, _, _)
        s match{
          case Student(name,age,sno) => println("this is student!")
        }
        //下面語句才達到sealed case class的要求
        s match{
          case Student(name,age,sno) => println("this is student!")
          case Teacher(name,age,tno) => println("this is teacher!")
          case Nobody(name) => println("Nobody")
        }
      }
    }
    //Person最前面加了個關鍵字sealed
    sealed abstract class Person
    case class Student(name:String,age:Int,sno:Int) extends Person
    case class Teacher(name:String,age:Int,tno:Int) extends Person
    case class Nobody(name:String) extends Person

三.匹配模式

  

  object caseTest {
      def main(args: Array[String]): Unit = {
        //1.常量模式與變量模式
        def patternShow(x:Any) = x match{
          //常量模式
          case 1 => "one"
          case true => "true"
          case "str" => "string"
          case null => "null"
          case Nil => "empty list"
          //變量模式
          case y => y
        }
        println(patternShow(1))
        //2.構造器模式
        val p = new Person("James",33)
        def conPattern(p:Person) = p match{
          case Person(name,age) => "Person"
          case _ => "Other"
        }
        //3.序列模式
        //序列模式:類似Array、List這樣的序列集合進行模式匹配
        val q = List("spark","hive","hadoop")
        def seqPattern(q:List[String]) = q match{
          //只需要匹配第二個元素
          case List(_,second,_*) => second
          case _ => "Other"
        }
        println(seqPattern(q))
        //4.元組模式
        //匹配某個元組內容
        val t = ("spark","hive","hadoop")
        def tuplePattern(t:Any) = t match{
          case (one,_,_) => one
          case _ => "other"
        }
        println(tuplePattern(t))
        //5.類型模式
        def typePattern(t:Any) = t match{
          case t:String => "String"
          case t:Int => "Integer"
          case t:Double => "Double"
        }
        println(typePattern(50.3))
        //等同於
        def typePatternIf(t:Any) = {
          if(t.isInstanceOf[String]) "String"
          else if(t.isInstanceOf[Int]) "Int"
          else if(t.isInstanceOf[Double]) "Double"
          else if(t.isInstanceOf[Map[_,_]]) "MAP"
        }
        //6.變量綁定模式
        val a = List(List(1,2,3),List(2,3,4))
        def varBindPattern(t:Any) = t match{
          //變量綁定,採用變量名(這裏使用e)與@符號。如果後面模式匹配成功,則將匹配結果返回
          case List(_,e@List(_,_,_)) => e
          case _ => Nil
        }
        println(varBindPattern(a))
      }
    }
    //構造器模式必須將類定義爲case class
    case class Person(name:String,age:Int)

四.For循環中的模式匹配

  

  object caseTest1 {
      def main(args: Array[String]): Unit = {
        val map = Map("Jack" -> 100, "Lily" -> 93, "James" -> 90, "Robin" -> 87)
        for ((name, score) <- map) {
          println(name + "->" + score)
        }
        //正則匹配案例
        val ip = "(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)".r
        for (ip(one, two, three, four) <- ip.findAllIn("192.168.1.10")) {
          println("IP子段1:" + one)
          println("IP子段2:" + two)
          println("IP子段3:" + three)
          println("IP子段4:" + four)
        }
      }
    }

五.Option類型模式匹配

Option類及其子類的源碼:

    //Option類的部分源碼
    sealed abstract class Option[+A] extends Product with Serializable {
      self =>
      def isEmpty: Boolean
      def isDefined: Boolean = !isEmpty
    }
     
    //Some類的部分源碼
    final case class Some[+A](x: A) extends Option[A] {
      def isEmpty = false
      def get = x
    }
     
    //None類的部分源碼
    case object None extends Option[Nothing] {
      def isEmpty = true
      def get = throw new NoSuchElementException("None.get")
    }

Option類型模式使用案例:

    //Option是sealed class,它有兩個子類:Some、None(單例對象)。
    val map = Map("hive"->2,"spark"->3,"Spark MLlib"->4)
    def mapPattern(t:String) = map.get(t) match{
      case Some(x) => println(x);x
      case None => println("None");-1
    }
    println(mapPattern("Hive")) // None -1

None是一個Case Object,它同Some一樣都extends Option類,只不過Some是Case Class。接下來我們模擬一下這三個類之間的關係:
 

//下面的類主要用於模擬Option,Some,None三個類或對象之間的關係
sealed abstract class A
case class B(name:String,age:Int) extends A
case object CaseObject extends A{
 
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章