1.31

特殊方法 apply/unapply/unapplySeq/update

形式x(...)相当于调用apply()方法;用于赋值等号左侧时,形如x(...)=y,相当于调用update(..., y)

伴生对象的apply方法多用于提供伴生类实例,省去new操作符。

unapply有逆apply之语义,但更广泛,是一种抽取行为(extract),定义了如何从一个量中抽取出若干个量。

unapply方法可定义在scala object或class中,捕获抽取出的量的形式为ObjectName(varName1,...)classInstance(varName1,...),unapply需返回Option,Option[Type]的类型参数Type即是捕获变量的类型,返回元组时允许捕获多个变量(和元组元素个数相同,编译期固定),unapplySeq返回Option[Seq[Type]]允许返回序列,允许动态(运行时)捕获多个量。

对于scala object定义unapply/unapplySeq情形主要提醒的一点是,并不要求该object有伴生class,捕获变量时当然也没有任何构造函数被调用。

class XYPoint(x:Int, y:Int){
}
object XYPoint{
    def unapply(p:XYPoint)= /*if ... None else */ Some((p.x, p.y))
}

object Point {  // no companion class, not to mention the constructor Point(Int,Int)
    def unapply(s:String)=Try(s.split(",")).filter(_.length==2).map(x=>(x(0),x(1))).toOption
}

objects Names{ // no companion class
    def unapplySeq(s:String)=Some(s.split(","))
}

object app extends App {
    val p=new XYPoint(1,2)   // or XYPoint(1,2) if apply defined in companion object
    val (x,y)=p     // yield variables x = p.x, y = p.y
    
    val Point(a,b)="50,100"  // a=50, b=100, Note: no class Point, not to mention the constructor Point(Int,Int)
    
    val s=scala.io.StdIn.readLine
    s match {
        case Names(n1) => ...  // a name, no ','
        case Nmaes(n1, n2) => ... // two names separated by ','
        case Names(n1,n2,n3)=>....
    }
}

对于抽取器用于变量声明时,如果返回None会导致运行时抛出Error,如果用于match,表示匹配不上该case。

case class自动具备apply、unapply。

posted @ 2024-01-31 08:44  秋渡晚枫  阅读(31)  评论(0)    收藏  举报