easy-algorithm-interview-an.../code-languages/scala/scala中的apply方法与unapply方法.md

3.0 KiB
Raw Permalink Blame History

1.apply方法

当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