scala 系列之 12scala 的 apply 和 unapply 方法

教程 潘牛 ⋅ 于 2021-07-08 22:52:20 ⋅ 1707 阅读

15 apply和unapply方法

apply、unapply方法都被隐式的调用

apply方法:

​ 1)在一个类的伴生对象中定义apply方法,在生成这个类的对象时,就省去了new关键字。

​ 2)apply方法的参数列表不需要和构造函数的参数列表统一,也就是说apply 方法支持重载。

​ 3)apply 方法可以通过主构造器和辅助构造器new对象;

​ 4)apply方法 定义在object 里,是创建对象;如果定义在class 里,是获取对象的数据;

apply方法定义在object对象

package day03
class ApplyDemo(val name:String) {
  var age:Int = _
  def this(name:String, age:Int) = {
    this(name)
    this.age = age
  }
}
object ApplyDemo{
  // 在 object对象上定义apply方法是用来创建对象的
  // 调用主构造器创建对象
  def apply(name: String): ApplyDemo = {
    println("==> apply(name: String)")
    new ApplyDemo(name)
  }
  // 调用辅助构造器创建对象
  // apply方法是可以重载的
  def apply(name: String, age:Int): ApplyDemo = {
    println("==> apply(name: String, age:Int)")
    new ApplyDemo(name, age)
  }

  def main(args: Array[String]): Unit = {
    // 直接new对象
    val demo = new ApplyDemo("hainiu")
    // 通过scala隐式的调用apply方法(主构造器)创建对象,此时不需要new关键字
    val demo2 = ApplyDemo("hainiu")
    println(demo2.name)

    // 通过隐式调用apply方法(调用的辅助构造器)来创建对象
    val demo3 = ApplyDemo("hainiu", 10)
    println(s"${demo3.name}, ${demo3.age}")
  }
}

apply方法定义在class上

package day03
class ApplyDemo2 {
  private val list = List(1,5,2,3,6,7)
  // apply 方法定义在class上是用来提取数据的
  // 就相当于数组、列表提取数据一样
  def apply(index:Int) = {
    this.list(index)
  }
}
object ApplyDemo2{
  def main(args: Array[String]): Unit = {
    val demo = new ApplyDemo2
    println(demo.apply(0))
    println(demo(0))
  }
}

unapply方法

​ 1)可以认为unapply方法是apply方法的反向操作,apply方法接受构造参数变成对象,而unapply方法接受一个对象,从中提取值。

​ 2)unapply方法常被称为提取方法,可以用unapply方法提取相同操作的对象,unapply方法会返回一个Option,其内部生成一个Some对象,这个Some是做相似对象的封装。

​ 3)unapply 不支持重载。

​ 4)unapply常被用于模糊匹配。

Option
Option中的泛型个数影响unapply方法返回some参数的个数和模式匹配中的case类型参数的个数。
Option 子类:
None:无数据,scala 用None 来表达 无数据, 相当于java 的 null
Some:有数据。
用的地方:
1)模式匹配
2)集合

package day03
class UnapplyDemo(val name:String, val age:Int) {
}
object UnapplyDemo{
  // unapply方法是用来解构的
  // 你给我对象,我把对象里的数据提取出来(通过模式匹配)
  def unapply(arg: UnapplyDemo): Option[(String, Int)] = {
    println("==> unapply(arg: UnapplyDemo): Option[(String, Int)]")
    Some((arg.name, arg.age))
  }
//  unapply方法不能重载
//  def unapply(arg: UnapplyDemo): Option[String] = {
//    println("==> unapply(arg: UnapplyDemo): Option[(String, Int)]")
//    Some(arg.name)
//  }
  def main(args: Array[String]): Unit = {
    val demo = new UnapplyDemo("hainiu", 10)
    demo match{
        // type1: 由于是直接匹配对象,所以不需要走unapply方法
//      case x : UnapplyDemo => println(s"type1==>${x.name}, ${x.age}")
        // 下面的都是提取对象里面数据的,这些都走unapply方法
      case UnapplyDemo(x,y) => println(s"type2==>${x}, ${y}")
      case UnapplyDemo(x) => println(s"type3==>${x._1}, ${x._2}")
      case UnapplyDemo("hainiu", y) => println(s"type4==>hainiu, ${y}")
    }
  }
}

总结:

​ apply 方法定义 object 中,用于创建对象;

​ apply方法定义 class 中, 用于提取数据;

​ unapply 方法 定义在 object 对象中, 用于提取对象数据;

版权声明:原创作品,允许转载,转载时务必以超链接的形式表明出处和作者信息。否则将追究法律责任。来自海汼部落-潘牛,http://hainiubl.com/topics/75747
成为第一个点赞的人吧 :bowtie:
回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter