scala的提取器(Extractor)

时间:2022-11-16 20:02:13

scala的提取器(Extractor)


在定义scala类的时候,如果额外自定义了unapply()方法,那么该类的对象就是一个提取器,我们就能从该对象中获取到构造该对象的值有哪些。

先来看一下没有定义unapply()方法的普通类——


(1)scala中普通类class

普通类需要通过new 操作来创建对象,每new 一个实例就创建一个全新的对象。


// 定义一个普通类

scala> class People(name:String, age:Int, city:String)

defined class People


// 通过new 操作来创建对象

scala> val cindy1 = new People("Cindy", 24, "Los Angeles")

cindy1: People = People@29394966


// cindy1和cindy2是两个不同的对象

scala> val cindy2 = new People("Cindy", 24, "Los Angeles")

cindy2: People = People@2c70a1de



再来看看定义了unapply()方法的类——


(2)携带提取器(Extractor)的类class

提取器:是一个带有unapply()方法的实例(对象)。

当我们对提取器对象使用match语句时, 会自动调用unapply()方法。


我们有时候需要使用提取器,以便从一个类的实例中获取:构造该实例的值有哪些。那么,只要把对象传递给unapply()方法,此方法就会从中提取出构造该对象的参数值。示例如下


object Customer {

   //编译器在实例化的时候,会自动调用 apply()方法

    def apply(name: String, age: Int, item: String):String = {

        name + "," + age + "," + item

    }

   /* unapply()方法是apply()的反向操作

     * 把对象传递给unapply()方法,此方法就会从中取出构造该对象的参数值。

     */

    def unapply(arg: String): Option[(String, Int, String)] = {

        val args_list = arg.split(",")

        if (args_list.length == 3) {

            Some((args_list(0), args_list(1).toInt, args_list(2)))

        }

        else None

    }

    def main(args: Array[String]) {

       //使用 apply() 方法则无需使用new 操作就能创建实例

        val obj1 = apply("Buddy", 32,"Beer")

        println("自动调用apply(),结果:\t" + obj1)

        println("调用unapply(),得到构造此对象的参数值列表:\t" + unapply(obj1))

        println("调用unapply():\t" + unapply("Goodman"))


        //编译器在实例化的时候,会自动调用 apply()方法

        val obj2 = Customer("Tony", 27,"Milk")

        println("编译器在实例化时自动调用apply(),结果: "+obj2)


       //对提取器对象 obj2 使用match语句,则自动调用unapply()

        obj2 match {

            case Customer(str) => printf("构造出对象 %s 的参数有: %s",obj2,str)

            case _ => println("nothing")

        }

    }

}


【运行 Customer 的输出结果】

自动调用apply(),结果:Buddy,32,Beer

调用unapply(),得到构造此对象的参数值列表:Some((Buddy,32,Beer))

调用unapply(): None

编译器在实例化时自动调用apply(),结果: Tony,27,Milk

构造出对象 Tony,27,Milk 的参数有: (Tony,27,Milk)



最后来看一下无需手动定义unapply()的样例类——


(3)样例类 case class

不同于普通类class ,样例类内置了apply和unapply方法,创建对象时不需要new。

通过样例类,我们可以直接通过实例调用unapply()方法获取构造该实例的值。


scala> case class User(name:String, age:Int, city:String)

defined class User


scala> User.

apply   curried   toString   tupled   unapply


// 通过 apply 方法, 无需使用 new 操作就能创建对象

scala> val tony = User.apply("tony", 27, "Peking")

tony: User = User(tony,27,Peking)


//查看由哪些值构造了此对象

scala> User.unapply(tony)

res5: Option[(String, Int, String)] = Some((tony,27,Peking))