scala基础之提取器extractor

一 apply & unapply方法

apply方法我们已经非常熟悉了,它帮助我们无需new操作就可以创建对象,而unapply方法则用于析构出对象,在模式匹配中特别提到,如果一个类要能够应用于模式匹配当中,必须将类声明为case class,因为一旦被定义为case class,scala会自动帮我们生成相应的方法,这些方法中就包括apply方法及unapply方法。本节将从提取器(也称析构器)的角度对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(p: Person):Option[(String,String)] = {
        if (p != null) Some(p.firstName, p.secondName)
        else None
   
}
}

object ExtractorClient extends App{
    val p=Person("nicky","zhang")
    p match {
        //析构出firstNamesecondeName
        case Person(firstName,secondName) => println("firstName="+firstName+" secondName="+secondName)
        case _ => println("null object")
    }
}

 

 

二 零变量或者单个变量的绑定模式匹配

前面的例子给定的是模式匹配两个变量,他可以扩展到任意维度,比如:

//Twice用于匹配重复出现的字符串,它绑定的是一个变量
//即返回的类型是Option[String]
object Twice {
    def apply(s: String): String = s + s
    def unapply(s: String): Option[String] = {
        val length = s.length / 2
        val 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 " + domain
        case _ =>
            "no match"
    }
    val email=EMail("摇摆少年梦摇摆少年梦","sina.com")
    println(userTwiceUpper(email))
}

 

代码中的EMail(Twice(x @UpperCase()),其执行顺序是先调用EMail的unapply方法,然后再调用Twice中的unapply方法,最后调用UpperCase的unapply方法,如果返回true,则将Twice 中返回的字符串赋值给x。

 

三 Scala中占位符总结

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 _ = 5

 

4、临时参数:Ignored parameters

List(1, 2, 3) foreach { _ =>println("Hi") }

 

5、通配模式:Wildcard patterns

Some(5) match { case Some(_) =>println("Yes") }

match {

     caseList(1,_,_) => " a list with three element and the first element is1"

     caseList(_*)  => " a list with zeroor more elements "

     caseMap[_,_] => " 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 butrenames Foo to Bar

import com.test.Fun.{ Foo => Bar , _ }

 

// Imports all the members except Foo. To exclude amember rename it to _

import com.test.Fun.{ Foo => _ , _ }

 

8、连接字母和标点符号:Joining letters to punctuation

def bang_!(x: Int) = 5

 

9、占位符语法: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 = {

    // Somecode

}

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)._2

 

13、参数序列: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: _*)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莫言静好、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值