Scala学习笔记--apply 方法详解

    • apply
      • 定义在 object 中
      • 定义在 class 或 trait 中
    • scala 的函数对象
    • unapply

关于scala中的特殊方法apply,先给一个比较通俗的解释。

当对象(伴生对象)以函数的方式进行调用时,scala 会隐式地将调用改为在该对象上调用apply方法。

例如: Demo(“hello”) 实际调用的是 Demo.apply(“hello”), 因此apply方法又被称为注入方法。

apply方法常用于创建类实例的工厂方法。

case class SomeBean(name: String, age: Int)

对于这个 case 类会生成一个 SomeBean 的伴生对象 SomeBean,这个伴生对象中定义了 apply 与 unapply 方法。
下面这段代码是反编译后得到的

public Option> unapply(SomeBean x$0) {
  return x$0 == null ? None..MODULE$ : new Some(new Tuple2(x$0.name(), BoxesRunTime.boxToInteger(x$0.age())));
}

public SomeBean apply(String name, int age) {
  return new SomeBean(name, age);
}

apply

将对象以函数的方式进行调用时,scala会隐式地将调用改为在该对象上调用apply方法。例如XXX(“hello”)实际调用的是XXX.apply(“hello”), 因此apply方法又被称为注入方法。apply方法常用于创建类实例的工厂方法。

定义在 object 中

object Greeting{
  def apply(name: String) = "Hello " + name
}

Greeting.apply(“Lucy”) //与下面的调用等价
Greeting(“Lucy”) //结果为 Hello Lucy

定义在 class 或 trait 中

首先我们来看下 scala 集合类 List 对 apply 的使用。scala 中 List 在读取数据时与 java 的 List 不同。
java 中使用 list.get(index) 取得第 index 个索引的数据,但在 scala 中只需要使用 list(index )就可以实现。
这个功能就是借助于 apply 方法实现的。例如:

List(1, 2, 3)
List("a", "b", "c")

或者是Map也有类似的用法:

Map(1 -> "a", 2 -> "b", 3 -> "c")

以上的两段代码并不是在调用 List 和 Map 的 constructor,而是在调用 List 和 Map 的伴生对象(companion objects)的 apply 方法。

下面我们来实际使用 apply 方法来显示获取特定位置的字符的需求(类似与模拟 Map 和 List 中的取值方法)

class IndexedString(val str: String) {
  def apply(charIndex: Int) = str.charAt(charIndex)
}

我们可以通过 IndexedString 的 apply 方法可以通过索引读取在字符中对应的字符

val indexed = new IndexedString("Hello world")
indexed(0) //结果为H, 等价于indexed.apply(0)

scala 的函数对象

scala 中的函数对象(头等函数或first-class function)是使用 apply 的典型用法:scala 中的函数对象是scala.FunctionN 特质的实例,使用时函数对象直接调用 FunctionN 的 apply 方法。

scala> val increment: (Int) => Int = _ + 1 
increment: Int => Int = 
// 调用 scala.FunctionN的apply方法
scala> increment(0)
res0: Int = 1

unapply

与 apply 相对的是 unapply 方法,它的用法与 apply 类似,但其作用是用来抽取部分参数,它也称为抽取方法,主要用于模式匹配时抽取某些参数 case XXX(str) => println(str)

你可能感兴趣的:(Scala)