scala的apply和unapply方法

scala中类或者对象有一个主要用途的时候,apply方法就是一个很好地语法糖。

请看下面一个简单的例子:

class Foo(foo: String) {
}

object Foo {
    def apply(foo: String) : Foo = {
        new Foo(foo)
    }
}

定义了一个Foo类,并且在这个类中,有一个伴生对象Foo,里面定义了apply方法。有了这个apply方法以后,我们在调用这个Foo类的时候,用函数的方式来调用:

object Client {

    def main(args: Array[String]): Unit = {
        val foo = Foo("Hello")
    }
}

我们用Foo("Hello")的方式,就得到了一个Foo类型的对象,这一切就是apply方法的功劳。如果没有apply方法,我们将需要使用new关键字来得到Foo对象。

2.apply方法用来做工厂

apply方法的最佳实践方式之一就是用来做工厂。比如在Scala的标准库中,许多集合类给我们提供了apply方法来创建集合:

object Client {

    def main(args: Array[String]): Unit = {
        val arr = new Array[Int](3)
        arr(0) = 0
        arr(1) = 1
        arr(2) = 2
        arr.foreach(x => print(x + " "))
        println()

        val array = Array(1,2,3)
        array.foreach(x => print(x + " "))
    }
}

上面两种方式我们都可以用来创建Array。第一种方式是使用new关键字,这是传统的面向对象的方式。那么第二种方式是什么情况呢?如果我们在IDE里点进去,可以发现IDE会提示我们有一个apply方法。点进去看apply方法的源码:

  /** Creates an array of `Int` objects */
  // Subject to a compiler optimization in Cleanup, see above.
  def apply(x: Int, xs: Int*): Array[Int] = {
    val array = new Array[Int](xs.length + 1)
    array(0) = x
    var i = 1
    for (x <- xs.iterator) { array(i) = x; i += 1 }
    array
  }

3.unapply方法

从上面的例子不难看出,apply方法有点类似于Java中的构造函数,接受构造参数变成一个对象。那么unapply方法就刚好相反,他是接受一个对象,从对象中提取出相应的值。
unapply方法主要用于模式匹配中。
看个简单的例子:

class Money(val value: Double, val country: String) {}

object Money {
    def apply(value: Double, country: String) : Money = new Money(value, country)

    def unapply(money: Money): Option[(Double, String)] = {
        if(money == null) {
            None
        } else {
            Some(money.value, money.country)
        }
    }
}

客户端实现:

    def testUnapply() = {
        val money = Money(10.1, "RMB")
        money match {
            case Money(num, "RMB") =>  println("RMB: " + num)
            case _ => println("Not RMB!")
        }
    }

最后输出为:

RMB: 10.1

所以下面那种创建数组的方式,其实是通过Array类的apply方法实现的。

参考文档:
1.https://stackoverflow.com/questions/9737352/what-is-the-apply-function-in-scala/9738862#9738862
2.https://twitter.github.io/scala_school/zh_cn/basics2.html

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

微信扫一扫

微信扫一扫

微信扫一扫,分享到朋友圈

scala的apply和unapply方法