日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Scala入门到精通——第二十五节 提取器(Extractor)

發布時間:2024/1/23 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Scala入门到精通——第二十五节 提取器(Extractor) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本節主要內容

  • apply與unapply方法
  • 零變量或變量的模式匹配
  • 提取器與序列模式
  • scala中的占位符使用總結
  • 1. apply與unapply方法

    apply方法我們已經非常熟悉了,它幫助我們無需new操作就可以創建對象,而unapply方法則用于析構出對象,在模式匹配中特別提到,如果一個類要能夠應用于模式匹配當中,必須將類聲明為case class,因為一旦被定義為case class,Scala會自動幫我們生成相應的方法,這些方法中就包括apply方法及unapply方法。本節將從提取器(也稱析構器)的角度對unapply方法進行介紹。先看下面的這個例子(來源于programmin in scala)

    object EMail{//apply方法用于無new構造對象def apply(user: String, domain: String) = user + "@" + domain//unapply方法用于在模式匹配中充當extractordef unapply(str: String): Option[(String, String)] = {val parts = str split "@"if (parts.length == 2) Some(parts(0), parts(1)) else None} } object ApplyAndUnapply {val email=EMail("zhouzhihubeyond","sina.com")//下面的匹配會導致調用EMail.unapply(email)case EMail(user,domain) => println("user="+user+" domain="+domain)} }
    • 1

    在上述的代碼中,我們將unapply方法定義為:
    def unapply(str: String): Option[(String, String)] = {
    val parts = str split "@"
    if (parts.length == 2) Some(parts(0), parts(1)) else None
    }

    這是有道理的,原因在于可能會有不合法的email用于模式匹配,例如:

    object ApplyAndUnapply extends App{def patternMatching(x:String)=x match {//下面的匹配會導致調用EMail.unapply(email)case EMail(user,domain) => println("user="+user+" domain="+domain)//匹配非法郵箱case _ => println("non illegal email")}val email=EMail("zhouzhihubeyond","sina.com")patternMatching(email) patternMatching("搖擺少年夢") }

    從構造與析構的角度來看,apply方法也被稱為injection(注入),unapply方法也被稱為提取器,這兩個方法就像孿生兄弟一樣,經常在類或對象中被定義。以前我們在用類進行模式匹配的時候都必須要將類聲明為case class,今天我們將不通過case class,而是定義一個普通的類實現自己的apply和unapply方法來實現模式匹配,代碼如下:

    //定義一個普通類 class Person(val firstName:String,val secondName:String)//在伴生對象中定義apply方法和unapply方法 object Person{def apply(firstName: String, secondName: String) = new Person(firstName,secondName)def unapply(person: Person):Option[(String,String)]={if(person!=null) Some(person.firstName,person.secondName)else None} }val p=Person("搖擺少年夢","周")p match {//析構出firstName,secondeNamecase Person(firstName,secondName) => println("firstName="+firstName+" secondName="+secondName)case _ => println("null object")}

    2. 零變量或單變量綁定的模式匹配

    上一節講的模式模式匹配綁定的是兩個變量,它可以擴展到任意變量維度,這一節中我們對零變量和單個變量綁定的特殊情況進行介紹,我們來看下面的這個例子,該例子來源于 programmin in scala

    //Twice用于匹配重復出現的字符串,它綁定的是一個變量 //即返回的類型是Option[String] object Twice {def apply(s: String): String = s + sdef unapply(s: String): Option[String] = {val length = s.length / 2val half = s.substring(0, length)if (half == s.substring(length)) Some(half) else None} } //未綁定任何變量,僅僅返回Boolean類型 object UpperCase {def unapply(s: String): Boolean = s.toUpperCase == s }object NonAndOneVariablePattern extends App{def userTwiceUpper(s: String) = s match {//下面的代碼相當于執行了下面這條語句//UpperCase.unapply(Twich.unapply(EMail.unapply(s)))case EMail(Twice(x @ UpperCase()), domain) =>"match: " + x + " in domain " + domaincase _ =>"no match"}val email=EMail("搖擺少年夢搖擺少年夢","sina.com")println(userTwiceUpper(email)) }

    代碼中的EMail(Twice(x @ UpperCase()),其執行順序是先調用EMail的unapply方法,然后再調用Twice中的unapply方法,最后調用UpperCase的unapply方法,如果返回true,則將Twice 中返回的字符串賦值給x。

    3. 提取器與序列模式

    List伴生對象具有下列定義形式:

    object List { def apply[T](elems: T*) = elems.toList def unapplySeq[T](x: List[T]): Option[Seq[T]] = Some(x) ... }

    從上面的代碼來看,與一般的提取器不同的是,序列模式采用unapplySeq代替unapply方法,并且返回的類型是Option[Seq[T]] ,在講模式匹配的時候我們提到過,序列模式中的匹配經常會使用占位符_或_*的方式匹配序列中的其它元素,這種方式為序列模式所獨有,例如:

    object ExtractorSequence extends App{val list=List(List(1,2,3),List(2,3,4))list match {//_*表示匹配列表中的其它元素case List(List(one,two,three),_*) => println("one="+one+" two="+two+" three="+three)case _ => println("Other")}list match {//_表示匹配列表中的第一個元素//_*表示匹配List中的其它多個元素//這里采用的變量綁定的方式case List(_,x@List(_*),_*) => println(x)case _ => println("other list")} }

    4. scala中的占位符使用總結

    scala作為一種函數式編程語言,有很多地方會讓初學者覺得困惑,其中占位符_的使用理解有一定的難度,本節將對其使用進行總結,本小節內容來源http://my.oschina.net/leejun2005/blog/405305,感謝作者的無私奉獻。

    1、存在性類型:Existential types def foo(l: List[Option[_]]) = ...2、高階類型參數:Higher kinded type parameters case class A[K[_],T](a: K[T])3、臨時變量:Ignored variables val _ = 54、臨時參數:Ignored parameters List(1, 2, 3) foreach { _ => println("Hi") }5、通配模式:Wildcard patterns Some(5) match { case Some(_) => println("Yes") } match {case List(1,_,_) => " a list with three element and the first element is 1"case List(_*) => " a list with zero or more elements "case Map[_,_] => " matches a map with any key type and any value type "case _ =>} val (a, _) = (1, 2) for (_ <- 1 to 10)6、通配導入:Wildcard imports import java.util._7、隱藏導入:Hiding imports // Imports all the members of the object Fun but renames Foo to Bar import com.test.Fun.{ Foo => Bar , _ }// Imports all the members except Foo. To exclude a member rename it to _ import com.test.Fun.{ Foo => _ , _ }8、連接字母和標點符號:Joining letters to punctuation def bang_!(x: Int) = 59、占位符語法:Placeholder syntax List(1, 2, 3) map (_ + 2) _ + _ ( (_: Int) + (_: Int) )(2,3)val nums = List(1,2,3,4,5,6,7,8,9,10)nums map (_ + 2) nums sortWith(_>_) nums filter (_ % 2 == 0) nums reduceLeft(_+_) nums reduce (_ + _) nums reduceLeft(_ max _) nums.exists(_ > 5) nums.takeWhile(_ < 8)10、偏應用函數:Partially applied functions def fun = {// Some code } val funLike = fun _List(1, 2, 3) foreach println _1 to 5 map (10 * _)//List("foo", "bar", "baz").map(_.toUpperCase()) List("foo", "bar", "baz").map(n => n.toUpperCase())11、初始化默認值:default value var i: Int = _12、作為參數名: //訪問map var m3 = Map((1,100), (2,200)) for(e<-m3) println(e._1 + ": " + e._2) m3 filter (e=>e._1>1) m3 filterKeys (_>1) m3.map(e=>(e._1*10, e._2)) m3 map (e=>e._2)//訪問元組:tuple getters (1,2)._213、參數序列:parameters Sequence _*作為一個整體,告訴編譯器你希望將某個參數當作參數序列處理。例如val s = sum(1 to 5:_*)就是將1 to 5當作參數序列處理。 //Range轉換為List List(1 to 5:_*)//Range轉換為Vector Vector(1 to 5: _*)//可變參數中 def capitalizeAll(args: String*) = {args.map { arg =>arg.capitalize} }val arr = Array("what's", "up", "doc?") capitalizeAll(arr: _*)

    總結

    以上是生活随笔為你收集整理的Scala入门到精通——第二十五节 提取器(Extractor)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。